La composición es cuando una clase ofrece alguna funcionalidad al crear una instancia de una clase (posiblemente interna) que ya implementa esta funcionalidad, en lugar de heredar de esa clase.
Entonces, por ejemplo, si tiene una clase que modela un barco, y ahora le dicen que su barco debe ofrecer un helipuerto, no es natural derivar su barco de un helipuerto, ¡en cambio, debería tener su nave contiene una clase de helipuerto y la expone a través de algún Ship.getHelipad()
método.
En años antiguos (hace una década más o menos), la gente solía ver la herencia como una forma rápida y fácil de agregar funcionalidad, por lo que había muchos ejemplos del tipo de "barco heredado del helipuerto", que, por supuesto, eran muy lamentables.
Pero la frase "Favorecer la composición sobre la herencia" se ha redactado cuidadosamente para dejar en claro que esto es solo una sugerencia, no una regla. El autor del dicho fue lo suficientemente cuidadoso como para abstenerse de decir algo como " nunca usarás la herencia, solo la composición". Básicamente, esto llama la atención de la comunidad de ingenieros de software sobre el hecho de que la herencia se ha utilizado en exceso, mientras que en muchos casos, la composición produce diseños más claros, elegantes y sostenibles que la herencia.
Entonces, esencialmente, el dictamen "Favorecer la composición sobre la herencia" sugiere que cada vez que se enfrente con "¿heredar o componer?" pregunta, debería pensar detenidamente cuál es la estrategia más adecuada, y que lo más probable es que la estrategia más adecuada resulte ser composición, no herencia.
Pero como esto no es una regla, también debe tener en cuenta que hay muchos casos en los que la herencia es más natural. Si usa la composición allí donde debería haber usado la herencia, muchos males caerán sobre su código.
Para volver al ejemplo del barco, si su barco necesita ofrecer una interfaz para interactuar con un FloatingMachine
, entonces es más natural derivarlo de una FloatingMachine
clase abstracta , que muy posiblemente podría derivarse de otra Machine
clase abstracta .
Aquí está la regla general para la respuesta a la pregunta de composición vs. herencia:
¿Mi clase tiene una relación "es un" con la interfaz que necesita exponer? En caso afirmativo, use la herencia. Si no, use la composición.
Un barco "es una" máquina flotante, y una máquina flotante "es una" máquina. Entonces, la herencia está perfectamente bien para aquellos. Pero un barco no es, por supuesto, un helipuerto. Por lo tanto, es mejor componer la funcionalidad del helipuerto.