miércoles, 7 de abril de 2010

Cómo trabajar con programación orientada a objetos.

¿Cómo se interactúa con clases en la programación orientada a objetos? Un objeto es una instanciación de una clase, es decir, una clase es como un "plano" o un "diseño" de lo que será un objeto. Cuando se instancia la clase el diseño de la propia clase toma "forma" creándose el objeto que en la clase se ha diseñado.

Por tanto una clase no interactúa con otra, sino los objetos que se crean a partir de las clases. Por tanto la pregunta a continuación sería, ¿cómo interactúan los objetos en programación orientada a objetos?

Los conceptos más importantes de un objeto (que no las únicos) son:

El constructor: el código que se ejecuta cuando se instancia una clase (cuando se crea el objeto).
El destructor: el código que se ejecuta cuando se destruye un objeto.
Los métodos: Mecanismo con el que los objetos se interrelacionan entre sí.
Atributos (o variables): Características de un objeto, que lo definen.

Esto que parece algo confuso en realidad no lo es tanto. Una cosa es trabajar con clases y al instanciarlas con objetos, y otra muy distinta es programar con el paradigma de orientación a objetos. Un ejemplo muy simple lo podemos ver en el caso en el que se define una clase con un único método. Eso no es una clase, es una función global que se encapsula, erróneamente, en una clase.

Pasemos a ver un ejemplo de una clase con atributos (que la definen) y con métodos que operan sobre dichos atributos. Además dichos métodos se utilizan para comunicarse con otras entidades (otros objetos).

El ejemplo trata sobre una clase con un único atributo y 6 métodos. Se puede observar un método especial, llamado __init__. Aquí es donde se pueden inicializar las variables internas que utilizará el objeto así como la inicialización de los atributos. Es lo más parecido a un constructor, aunque técnicamente no lo es, ya que el objeto ya está creado cuando se ejecuta su código. Sin embargo, si queremos ejecutar algo que debería de ejecutarse en el constructor, este es el sitio indicado.

# -*- coding: cp1252 -*-
# Ejemplo de uso de clases e interacción enter objetos.
# El Viaje del Navegante.
# 07-04-2010.

class numero(object):
'''
Clase que representa un número, junto con sus posibles operaciones.
'''
def __init__(self, inicializador_numero):
self.numero = inicializador_numero

def sumar(self, operando1, operando2):
return operando1 + operando2

def restar(self,operando1, operando2):
return operando1 - operando2

def multiplicar(self, operando1, operando2):
return operando1 * operando2

def cambiar_signo(self):
self.numero = self.numero * (-1)

def dividir(self, operando1, operando2):
# Devuelve la tupla (operando1//operando2, operando1%operando2)
return divmod(operando1, operando2)

def valor(self):
return self.numero


Pasemos a ver los diversos ejemplos:

Instanciamos una clase número, creando un objeto con un valor inicial de 7.

n1 = numero(7)

Tenemos un objeto que internamente tiene un único atributo, cuyo valor es 7. Vamos a operar
sobre ese valor, de modo que mediante uno de sus métodos vamos a cambiarle su signo.

n1.cambiar_signo()

Devolvemos el valor que actualmente tiene el objeto (su estado).

print "Valor con signo cambiado: ", n1.valor()

Devuelve -7.

Creamos otro objeto, que tendrá un valor inicial de 10.

n2 = numero(8)

Ahora vamos a utilizar un método del objeto n1 para sumar los valores (estados) que tienen actualmente los objetos n1 y n2. Darse cuenta que con este ejemplo quiero indicar que los objetos sirven para retener y modificar datos. De esta manera, mediante métodos se puede manipular información que está encapsulada dentro de una estructura (el objeto). Esto implica seguridad y sobretodo, control (aparte de una tremenda elegancia, cosa importante que con el tiempo se aprecia)

print "Suma de dos números: ", n1.sumar(n1.valor(), n2.valor())

Devuelve 1.

En el ejemplo anterior vemos cómo están interactuando 2 objetos. Los objetos interactúan a través de sus métodos. También hubiera sido completamente correcto esto:

print "Suma de dos números: ", n1.sumar(n1.numero, n2.numero)

También devuelve 1.

¿Y por qué no soy partidario de esta última forma? Pues por la sencilla razón que aquí estamos accediendo directamente a un atributo, operando directamente sobre él, sin el control de lo que se podría hacer (cosa que tenemos cointrolada si utilizamos métodos, ya que sabemos cuales son los límites). Hay lenguajes cono C# ó Java en donde hay modificacores de acceso (public, private y demás) que dan ciertas restricciones a la hora de acceder a atributos de un objeto.

En Python está implementado un mecanismo parecido, pero que puede saltarse con facilidad. A este mecanismo en POO se le llama encapsulación.

Para indagar más sobre POO en Python os recomiendo la lectura del siguiente artículo en este blog: El viaje del navegante: Clases y objetos en Python, para entendernos.

Saludos.

1 comentario: