patterns over oop inheritance composition

oop - over - "Es un" vs "Tiene un": ¿cuál es mejor?



composition over inheritance javascript (8)

Cartera A -> Fondo 1

Cartera A -> Fondo 2

Portafolio A -> Fondo 3

No pude enmarcar mi oración sin usar is / has. Pero entre 1 y 2,

1) tiene un:

class PortfolioA { List<Fund> obj; }

2) es un:

class PortfolioA : List<Fund> { }

¿Cuál crees que es mejor desde el punto de extensibilidad, usabilidad? Todavía puedo acceder a mis fondos de cualquier manera, aunque con un pequeño cambio sintáctico.


La nave de relación IS-A representa las herencias y la relación de la nave HAS-A representa la composición. Para el escenario mencionado anteriormente, preferimos la composición ya que PortfolioA tiene una lista y no es el tipo de lista. Las herencias se utilizan cuando la cartera A es un tipo de lista, pero aquí no. Por lo tanto, para este escenario, deberíamos preferir la Composición.


Depende de si el negocio define una Cartera como un grupo (y solo un grupo) de fondos. Si existe la remota posibilidad de que pueda contener otros objetos, diga "propiedad", luego vaya con la opción 1. Vaya con la opción 2 si existe un vínculo fuerte entre un grupo de fondos y el concepto de Cartera.

En cuanto a extensibilidad y utilidad 1 tiene la ligera ventaja sobre 2. Realmente no estoy de acuerdo con el concepto de que siempre debes favorecer a uno sobre el otro. Realmente depende de cuáles sean los conceptos reales de la vida real. Recuerde, siempre puede ^ refactorizar.

^ Para la mayoría de los casos de siempre. Si está expuesto públicamente, entonces obviamente no.


Diferiré con lo que parece ser la opinión común. En este caso, creo que una cartera es muy poco más que una colección de fondos ... Al usar la herencia, permite el uso de múltiples constructores, como en

public Portfolio(CLient client) {}; public Portfolio(Branch branch, bool Active, decimal valueThreshold) { // code to populate collection with all active portfolios at the specified branch whose total vlaue exceeds specified threshold }

e indexadores como en:

public Fund this[int fundId] { get { return this.fundList[fundId]; } }

etcétera etcétera.

si desea poder tratar las variables de tipo Portafolio como una colección de fondos, con la sintaxis asociada, este es el mejor enfoque.

Portfolio BobsPortfolio = new Portfolio(Bob); foreach (Fund fund in BobsPortfolio) { fund.SendStatement(); }

o cosas por el estilo


El primero, porque es "consiste en" . => Composición


Me gustaría ir con la opción (1) - composición, ya que eventualmente puede tener atributos específicos de la cartera, en lugar de los fondos.


Voto con las otras personas que dicen que HAS-A es mejor en este caso. Usted pregunta en un comentario:

cuando digo que una Cartera es solo una colección de fondos, con algunos atributos propios como TotalPortfolio, etc., ¿eso no se convierte fundamentalmente en un "is-a"?

No lo creo. Si dice Portfolio IS-A List<Fund> , ¿qué pasa con otras propiedades de la Cartera? Por supuesto, puede agregar propiedades a esta clase, pero ¿es correcto modelar esas propiedades como propiedades de la lista? Porque eso es básicamente lo que estás haciendo.

Además, ¿qué ocurre si se requiere una Cartera para admitir más de una List<Fund> ? Por ejemplo, puede tener una lista que muestre el saldo actual de las inversiones, pero otra lista que muestre cómo se invierten las nuevas contribuciones. ¿Y qué sucede cuando se suspenden los fondos y se utiliza un nuevo conjunto de fondos para sucederlos? La información histórica es útil para rastrear, así como la asignación de fondos actual.

El punto es que todas estas propiedades no son propiedades correctas de una Lista, aunque pueden ser propiedades de la Cartera.


no ''siempre'' favorezca la composición o la herencia o viceversa; ellos tienen diferentes semánticas (significados); mira cuidadosamente los significados, luego decide: no importa si uno es "más fácil" que el otro, para la longevidad es importante que obtengas la semántica correcta

recuerda: is-a = tipo, has-a = contención

entonces, en este caso, una cartera lógicamente es una colección de fondos; una cartera en sí misma no es un tipo de fondo , por lo que la composición es la relación correcta

EDITAR: He leído mal la pregunta originalmente, pero la respuesta sigue siendo la misma. Una Cartera no es un tipo de lista, es una entidad distinta con sus propias propiedades. Por ejemplo, una cartera es un agregado de instrumentos financieros con un costo de inversión inicial, un valor actual total, un historial de valores a lo largo del tiempo, etc., mientras que una Lista es una simple colección de objetos. Una cartera es un "tipo de lista" solo en el sentido más abstracto.

EDITOR 2: piense en la definición de cartera: es, sin excepción, caracterizada como una colección de cosas. La cartera de un artista es una colección de sus obras de arte, la cartera de un diseñador web es una colección de sus sitios web, la cartera de un inversor consta de todos los instrumentos financieros que poseen, y así sucesivamente. Entonces, claramente, necesitamos una lista (o algún tipo) para representar una cartera, ¡pero eso de ninguna manera implica que una cartera sea un tipo de lista!

supongamos que decidimos dejar que Portfolio herede de List. Esto funciona hasta que agreguemos un Stock o Bond o un Metal precioso a la Cartera, y de repente, la herencia incorrecta ya no funciona. O supongamos que se nos pide que modelemos, digamos, la cartera de Bill Gates, y descubramos que la Lista se quedará sin memoria ;-) Más realistamente, después de la refactorización futura probablemente descubriremos que deberíamos heredar de una clase base como Asset, pero si ya hemos heredado de List, entonces no podemos.

Resumen: distingue entre las estructuras de datos que elegimos para representar un concepto y la semántica (jerarquía de tipos) del concepto en sí.


El primero, porque deberías tratar de favorecer la composición sobre la herencia cuando puedas.