Module (50%)
Section (52%)

Cómo construir una jerarquía de clases: continuación

La herencia no es la única forma de construir clases adaptables. Puedes lograr los mismos objetivos (no siempre, pero muy a menudo) utilizando una técnica llamada composición.

La composición es el proceso de componer un objeto usando otros objetos diferentes. Los objetos utilizados en la composición entregan un conjunto de rasgos deseados (propiedades y / o métodos), podemos decir que actúan como bloques utilizados para construir una estructura más complicada.

Puede decirse que:

  • La herencia extiende las capacidades de una clase agregando nuevos componentes y modificando los existentes; en otras palabras, la receta completa está contenida dentro de la clase misma y todos sus ancestros; el objeto toma todas las pertenencias de la clase y las usa.
  • La composición proyecta una clase como contenedor capaz de almacenar y usar otros objetos (derivados de otras clases) donde cada uno de los objetos implementa una parte del comportamiento de una clase.

Permítenos ilustrar la diferencia usando los vehículos previamente definidos. El enfoque anterior nos condujo a una jerarquía de clases en la que la clase más alta conocía las reglas generales utilizadas para girar el vehículo, pero no sabía cómo controlar los componentes apropiados (ruedas o pistas).

Las subclases implementaron esta capacidad mediante la introducción de mecanismos especializados. Hagamos (casi) lo mismo, pero usando composición. La clase, como en el ejemplo anterior, sabe cómo girar el vehículo, pero el giro real lo realiza un objeto especializado almacenado en una propiedad llamada controlador. El controlador es capaz de controlar el vehículo manipulando las partes relevantes del vehículo.

Echa un vistazo al editor: así es como podría verse.

Existen dos clases llamadas Pistas y Ruedas - ellas saben cómo controlar la dirección del vehículo. También hay una clase llamada Vehiculo que puede usar cualquiera de los controladores disponibles (los dos ya definidos o cualquier otro definido en el futuro): el controlador se pasa a la clase durante la inicialización.

De esta manera, la capacidad de giro del vehículo se compone de un objeto externo, no implementado dentro de la clase Vehiculo.

En otras palabras, tenemos un vehículo universal y podemos instalar pistas o ruedas en él.

El código produce el siguiente resultado:

ruedas: True True ruedas: True False pistas: False True pistas: False False

Code

import time

class Pistas:
def cambiardireccion(self, izquierda, on):
print("pistas: ", izquierda, on)

class Ruedas:
def cambiardireccion(self, izquierda, on):
print("ruedas: ", izquierda, on)

class Vehiculo:
def __init__(self, controlador):
self.controlador = controlador

def girar(self, izquierda):
self.controlador.cambiardireccion(izquierda, True)
time.sleep(0.25)
self.controlador.cambiardireccion(izquierda, False)

conRuedas = Vehiculo(Ruedas())
conPistas = Vehiculo(Pistas())

conRuedas.girar(True)
conPistas.girar(False)
{{ dockerServerErrorMsg }} ×
{{ errorMsg }} ×
{{ successMsg }} ×