Llamamos delegación a la situación en la que una clase contiene (como atributos) una o más instancias de otra clase, a las que delegará parte de sus funcionalidades. Esta relación entre clases suele ser la más indicada cuando es necesaria una asociación entre las clases pero el principio de Liskov no se cumple. También puede verse como la relación entre clases "S contiene a T". Por ejemplo, Vehículo contiene un Motor, pero Alumno no contiene a Persona, sino que es una Persona.
Por ejemplo, la clase Hotel
vista en la unidad anterior, podría
contener una clase Disponibilidad
, que almacene la disponibilidad de
las habitaciones del hotel para distintas fechas. La clase Hotel
debería tener, entonces, los métodos consultar_disponibilidad
,
reservar
y cancelar
, que todos delegarían en la clase Disponibilidad
su funcionamiento principal.
Delegación y Referencias
Queremos construir una clase Rectangulo
, que se describe mediante los
siguientes atributos:
- Longitud de su base: un número.
- Longitud de su altura: un número.
- El punto del plano de su esquina inferior izquierda: un punto del plano.
# Código 15.1: Rectangulo.py: Clase para modelar un Rectángulo
#! /usr/bin/env python
#encoding: latin1
from Punto import Punto
class Rectangulo(object):
""" Esta clase modela un rectángulo en el plano. """
def __init__(self, base, altura, origen):
""" base (número) es la longitud de su base,
altura (número) es la longitud de su base,
origen (Punto) es el punto del plano de su esquina
inferior izquierda. """
self.base = base
self.altura = altura
self.origen = origen
def trasladar(self, dx = 0, dy = 0):
self.origen = self.origen + Punto(dx,dy)
def area(self):
return self.base * self.altura
def __str__(self):
""" muestra el rectángulo """
return "Base: %s, Altura: %s, Esquina inf. izq.: %s " %
(self.base, self.altura, self.origen)
Incluiremos métodos para inicializar y mostrar, para calcular el área y para trasladar el rectángulo en el plano.
La implementación básica puede verse en el código 15.1. Se puede ver
que el rectángulo realiza internamente la operación para calcular el
área, pero para la operación del traslado, delega la suma de los
puntos al operador __add__
de la clase Punto
.
Recordamos que cuando se hace self.origen + Punto(dx,dy)
, Python llama
al método __add__
de la clase Punto
, que recibe los dos puntos y
devuelve un nuevo punto con la suma de ambos.
Para construir y utilizar el rectángulo, lo haremos de la siguiente forma:
>>> from Punto import Punto
>>> from Rectangulo import Rectangulo
>>> r = Rectangulo(2, 3, Punto(1, 2))
>>> print r
Base: 2, Altura: 3, Esquina inf. izq.: (1, 2)
>>> print r.area()
6
Lo que acabamos de crear es un objeto de acuerdo al siguiente diagrama que se muestra en la Figura 15.3.
El punto que describe la posición de la esquina inferior izquierda del
rectángulo es un objeto Punto
. El atributo origen contiene una
referencia a dicho objeto.
Utilizando el método trasladar
, podemos modificar el valor del punto
contenido dentro del rectángulo.
>>> r.trasladar(2,4)
>>> print r
Base: 2, Altura: 3, Esquina inf. izq.: (3, 6)
También es posible directamente reemplazar el punto contenido, por un nuevo punto.
>>> q = Punto(7,2)
>>> r.origen = q
>>> print r
Base: 2, Altura: 3, Esquina inf. izq.: (7, 2)
Con lo cual el diagrama pasa a ser el de la Figura 15.3.
Nota El Punto(1, 2)
y Punto(3,6)
que habían sido creados previamente, están
ahora fuera de uso, por lo que quedan a disposición de un mecanismo de
recolección de basura, que no es tema de esta materia, que se
encarga de juntar todos los pedazos de memoria que se descartan
durante la ejecución de un programa.