Alguien preguntó a Michael Williams si podría hacer las versiones para Python y Java de su artículo: Una introducción a la programación Orientada a Objectos en C++. Aquí está una versión en Python del código. Comentaré respecto a las diferencias entre C++ y Python. ¿ Tal vez alguien pueda escribir la versión de Java ?
Estoy asumiendo que el lector sabe los fundamentos básicos de Python. Si no, ver el excelente Tutorial y otra documentación en http://www.python.org/doc/.
Para representar la casa de Michael (en la sección Classy! en el artículo de C++), podemos usar el siguiente código: (versión texto original)
#! /usr/bin/python
"""house.py -- Un programa de casas
Esta es un comentario, delimitado por tiples comillas.
"""
class House:
pass
my_house = House()
my_house.number = 40
my_house.rooms = 8
my_house.garden = 1
print "Mi casa tiene el número", my_house.number
print "ésta tiene", my_house.rooms, "habitaciones"
if my_house.garden:
garden_text = "tiene"
else:
garden_text = "no tiene"
print "Esta", garden_text, "un jardin"Al ejecutarse éste programa imprime ésto:
Mi casa tiene el número 40 ésta tiene 8 habitaciones ésta tiene un jardin
¿Que hace éste programa? Primero, definimos que es una
"casa" genérica en el bloque class. pass
significa "no hacer nada" y es requerido si el bloque
estará vacio. Entonces creamos una instancia (esto es, una
casa en particular) por medio de una llamada al nombre de la clase
como si fuera una función. La casa es entonces guardada en la
variable my_house.
Esta casa inicialmente no tiene atributos, -si hiciéramos
una consulta del valor de my_house.number antes de
asignarlo, obtendríamos un AttributeError. Las siguientes tres
líneas asignan y crean los atributos. Esta es una diferencia
entre los lenguajes: Las instancias de Java inician con ciertos
atributos los cuales nunca pueden cambiar (aún cuando sus
valores si pueden hacerlo), sin embargo las instancias de Python
inician sin atributos y se puede agregar o borrar atributos (o
cambiar su tipo) mas tarde. Esto permite que Python sea más
flexible en ciertas situaciones dinámicas.
Podemos inicializar la instancia al momento de su creación
por medio de la inclusión del método especial __init__
. (Un método es una función que "pertenece" a
una clase). Este programa: (versión
texto original)
#! /usr/bin/python
"""house2.py -- Otra casa.
"""
class House:
def __init__(self, number, rooms, garden):
self.number = number
self.rooms = rooms
self.garden = garden
my_house = House(20, 1, 0)
print "Mi casa es la número", my_house.number
print "ésta tiene", my_house.rooms, "habitaciones"
if my_house.garden:
garden_text = "tiene"
else:
garden_text = "no tiene"
print "ésta", garden_text, "un jardín"imprime:
Mi casa es la número 20 ésta tiene 1 habitaciones ésta no tiene un jardín
Debido a que la clase tiene un método __init__ ,
es llamado de manera automática cuando la instancia es creada.
Los argumentos de House son en realidad los argumentos
para __init__. Aun cuando la mayoría de los
progamas no lo hacen, se puede llamar a __init__
directamente cuantas veces se quiera: my_house.__init__(55, 14, 1).
Esto le indica al objecto que se "reinicialize a si mismo".
Ha de notarse que __init__ es definido con un primer
argumento extra, self. Pero no especificamos
self cuando llamamos al método. Todos los métodos
de Python trabajan así. self es de hecho la
instancia en sí misma que Python provee tras bambalinas. Se
necesita self porque es la única manera en que el
método puede acceder a los atributos de las instancias y a
otros métodos. Dentro del método, self.rooms
se refiere al atributo de la instancia rooms, pero rooms
se refiere a la variable local rooms.
Las variable locales, por supuesto, se desvanecen cuando el método
termina. El uso que hace Python de self tiene paralelo
en Perl y también en otros lenguajes Orientados a Objectos.
Michael no lo dijo, pero C++ tiene el apuntador this
el cual funciona como el self de Python. Ahora, en C++
no es neceario escribir this->house si es que no hay
una variable local house, y nunca se escribe this
en la línea de definición de un método. En otras
palabras , C++ (y Java) hacen la misma cosa que Python y Perl;
éstos solo que lo ocultan al programador.
De hecho, self en Python es sólo un nombre
convencional. Puedes llamarlo this o me
alternativamente si tu quieres. Personalmente a mi me gusta mas me.
Sin embargo, me quedo con self por si alguien tiene que
mantener mi trabajo después, le será más facil
leerlo y entenderlo. Por contraste, la variable this de
C++ es mágíca y no puede cambiársele el nombre.
En el programa en C++, garden es un atributo
booleano. Python no tiene atributos booleanos así que usamos
un entero en su lugar. La expresión my_house.garden
es verdadera si el atributo es 1 (u otro valor diferente de cero o
valor no vacio).
Esta sección corresponde a la sección de "Funciones
de Miembros" en el artículo de Williams. Yo prefiero el
término "método" sobre "funciones de
miembros", como los Pythoneros usualmente lo hacen. El programa
de Michael square.c se vería de ésta
manera: (versión
texto original)
#! /usr/bin/python
"""square.py -- Haz algunos ruidos al respecto del cuadrado.
"""
class Square:
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
return self.length * self.width
my_square = Square(5, 2)
print my_square.area()imprime
10
area debe ser explícito por si mismo debido a que
opera exactamente igual que el __init__ de arriba. Para
reiterar, todos los selfs en square.py son requeridos.
He escogido dar al programa Square un método __i n it__
en lugar de definir los atributos mas tarde debido a que eso es lo
que la mayoría de los programadores de Python harian.
Nada que decir al respecto. Python no permite métodos definidos fuera de una clase. Por supuesto, esto no aplica a las funciones ordinarias (que no son parte de una clase).
No mucho que decir aquí tampoco. Todos los atributos y métodos de Python son públicos. Se pueden emular atributos y métodos privados por vía del truco de la doble-subraya, sin emabargo la maypria de los programadores de Python no lo hacen. En su lugar, se cuenta con que el programador no abuse del API de la clase.
El método __init__ es el constructor.
El ejemplo de Williams de arreglos no puede ser codificado literalmente por las diferencias que existen entre los lenguajes, pero una versión equivalente es: (version texto original)
#! /usr/bin/python
"""person.py -- Un ejemplo de una persona.
"""
class Person:
def __init__(self, age, house_number):
self.age = age
self.house_number = house_number
alex = []
for i in range(5):
obj = Person(i, i)
alex.append(obj)
print "Alex[3] age is", alex[3].age
print
for alexsub in alex:
print "Age is", alexsub.age
print "House number is", alexsub.house_numberEsto imprime
Alex[3] age is 3 Age is 0 House number is 0 Age is 1 House number is 1 Age is 2 House number is 2 Age is 3 House number is 3 Age is 4 House number is 4
Python no tiene un equivalente a person alex[5] en
el programa en C++ el cual crea un arreglo de cinco instancias vacias
al mismo tiempo. En su lugar, creamos una lista vacia luego usamos
un ciclo o bucle for (el cual define i a 0,
1, 2, 3 and 4 respectivamente) para llenarla. El ejemplo muestra un
ciclo o bucle subscribiendo una lista por número de índice,
otro bucle el cual selecciona cada elemento de la lista directamente
y, una sentencia print que accesa un elemento por número
de índice.