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.

Estado de las variables, al momento de crear el rectángulo

Figura 15.1 Estado de las variables, al momento de crear el rectángulo

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.

Estado de las variables, luego de reemplazar el origen

Figura 15.2 Estado de las variables, luego de reemplazar el origen


Copyright (c) 2011-2014 Rosita Wachenchauzer, Margarita Manterola, Maximiliano Curia, Marcos Medrano, Nicolás Paez. La copia y redistribución de esta página se permite bajo los términos de la licencia Creative Commons Atribución - Compartir Obras Derivadas Igual 3.0 siempre que se conserve esta nota de copyright.