Prefere composição sobre inheritance?

Por que preferir composição sobre inheritance? Quais trade-offs existem para cada abordagem? Quando você deve escolher inheritance sobre composição?

Prefira composição sobre inheritance, pois é mais maleável / fácil de modificar depois, mas não use uma abordagem de compor sempre. Com a composição, é fácil mudar o comportamento rapidamente com Injeção / Configuração de Dependência. A inheritance é mais rígida, pois a maioria das linguagens não permite derivar de mais de um tipo. Assim, o ganso é mais ou menos cozido, uma vez que você deriva do TypeA.

Meu teste de ácido para o acima é:

  • O TypeB deseja expor a interface completa (nem todos os methods públicos) do TypeA para que o TypeB possa ser usado onde o TypeA é esperado? Indica inheritance .

Por exemplo, um biplano Cessna irá expor a interface completa de um avião, se não mais. Então, isso faz com que seja adequado derivar de avião.

  • O TypeB quer apenas parte / parte do comportamento exposto pelo TypeA? Indica a necessidade de composição.

Por exemplo, um pássaro pode precisar apenas do comportamento de voar de um avião. Neste caso, faz sentido extraí-lo como uma interface / class / ambos e torná-lo um membro de ambas as classs.

Atualização: Acabei de voltar à minha resposta e parece que agora está incompleta sem uma menção específica do Princípio de Substituição de Liskov de Barbara Liskov como um teste para “Devo ser herdeiro desse tipo?”

Pense em contenção como um relacionamento. Um carro “tem um” motor, uma pessoa “tem um” nome, etc.

Pense em inheritance como um relacionamento. Um carro “é um” veículo, uma pessoa “é um” mamífero, etc.

Eu não tenho nenhum crédito por essa abordagem. Eu peguei diretamente da Segunda Edição do Código Completo por Steve McConnell , Seção 6.3 .

Se você entende a diferença, é mais fácil explicar.

Código processual

Um exemplo disso é o PHP sem o uso de classs (particularmente antes do PHP5). Toda lógica é codificada em um conjunto de funções. Você pode include outros arquivos contendo funções auxiliares e assim por diante e conduzir sua lógica de negócios, passando dados nas funções. Isso pode ser muito difícil de gerenciar à medida que o aplicativo cresce. O PHP5 tenta remediar isso oferecendo mais design orientado a objects.

Herança

Isso incentiva o uso de classs. A inheritance é um dos três princípios do design OO (inheritance, polymorphism, encapsulamento).

class Person { String Title; String Name; Int Age } class Employee : Person { Int Salary; String Title; } 

Isso é inheritance no trabalho. O empregado “é uma” pessoa ou herda da pessoa. Todos os relacionamentos de inheritance são relacionamentos “é-um”. O funcionário também faz sombra à propriedade Title de Person, o que significa que Employee.Title retornará o título para o funcionário e não para a pessoa.

Composição

A composição é favorecida pela inheritance. Para simplificar, você teria:

 class Person { String Title; String Name; Int Age; public Person(String title, String name, String age) { this.Title = title; this.Name = name; this.Age = age; } } class Employee { Int Salary; private Person person; public Employee(Person p, Int salary) { this.person = p; this.Salary = salary; } } Person johnny = new Person ("Mr.", "John", 25); Employee john = new Employee (johnny, 50000); 

Composição é tipicamente “tem um” ou “usa um” relacionamento. Aqui, a class Employee possui uma Person. Ele não herda de Person, mas obtém o object Person passado para ele, e é por isso que ele “tem uma” Person.

Composição sobre inheritance

Agora, digamos que você queira criar um tipo de gerenciador para terminar com:

 class Manager : Person, Employee { ... } 

Este exemplo funcionará bem, no entanto, e se Person e Employee declararem Title ? O Manager.Title deve retornar “Manager of Operations” ou “Mr.”? Em composição, essa ambigüidade é melhor tratada:

 Class Manager { public Title; public Manager(Person p, Employee e) { this.Title = e.Title; } } 

O object Gerente é composto como um funcionário e uma pessoa. O comportamento do título é retirado do funcionário. Esta composição explícita remove a ambiguidade entre outras coisas e você encontrará menos erros.

Com todos os benefícios inegáveis ​​fornecidos pela inheritance, aqui estão algumas das suas desvantagens.

Desvantagens da inheritance:

  1. Você não pode alterar a implementação herdada das super classs em tempo de execução (obviamente porque a inheritance é definida em tempo de compilation).
  2. A inheritance expõe uma subclass a detalhes da implementação da class de seus pais, e é por isso que a inheritance quebra o encapsulamento (no sentido de que você realmente precisa se concentrar nas interfaces e não na implementação; portanto, reutilizar subclasss nem sempre é preferido).
  3. O acoplamento rígido fornecido pela inheritance torna a implementação de uma subclass muito vinculada à implementação de uma superclass que qualquer alteração na implementação pai forçará a subclass a mudar.
  4. Reutilização excessiva por subsorting pode tornar a pilha de inheritance muito profunda e muito confusa também.

Por outro lado, a composição do object é definida em tempo de execução através de objects que adquirem referências a outros objects. Nesse caso, esses objects nunca conseguirão alcançar os dados protegidos uns dos outros (sem quebra de encapsulamento) e serão forçados a respeitar a interface uns dos outros. E neste caso também, as dependencies de implementação serão muito menores do que no caso de inheritance.

Outra razão, muito pragmática, para preferir composição sobre inheritance tem a ver com seu modelo de domínio e mapeá-lo para um database relacional. É realmente difícil mapear a inheritance para o modelo SQL (você acaba com todos os tipos de soluções alternativas, como criar colunas que nem sempre são usadas, usando views, etc). Alguns ORMLs tentam lidar com isso, mas isso sempre fica complicado rapidamente. A composição pode ser facilmente modelada por meio de um relacionamento de chave estrangeira entre duas tabelas, mas a inheritance é muito mais difícil.

Embora em palavras curtas eu concorde com “Prefiro composição sobre inheritance”, muitas vezes para mim parece “preferir batatas ao invés de coca-cola”. Há lugares para inheritance e lugares para composição. Você precisa entender a diferença, então esta questão desaparecerá. O que isso realmente significa para mim é “se você vai usar inheritance – pense novamente, é provável que você precise de composição”.

Você deve preferir batatas ao invés de coca cola quando quiser comer, e coca cola com batatas quando quiser beber.

Criar uma subclass deve significar mais do que apenas uma maneira conveniente de chamar methods de superclass. Você deve usar inheritance quando a subclass “é-uma” superclass tanto estrutural quanto funcionalmente, quando ela puder ser usada como superclass e você vai usar isso. Se não for o caso – não é inheritance, mas alguma outra coisa. Composição é quando seus objects consistem em outro, ou tem algum relacionamento com eles.

Então, para mim, parece que se alguém não sabe se precisa de inheritance ou composição, o verdadeiro problema é que ele não sabe se quer beber ou comer. Pense mais no seu domínio do problema, entenda melhor.

A inheritance é bastante atraente, especialmente proveniente de terrenos processuais e, muitas vezes, parece enganosamente elegante. Quero dizer, tudo que eu preciso fazer é adicionar um pouco de funcionalidade a alguma outra class, certo? Bem, um dos problemas é que

inheritance é provavelmente a pior forma de acoplamento que você pode ter

Sua class base interrompe o encapsulamento, expondo os detalhes da implementação às subclasss na forma de membros protegidos. Isso torna seu sistema rígido e frágil. A falha mais trágica, no entanto, é que a nova subclass traz consigo toda a bagagem e a opinião da cadeia de inheritance.

O artigo, Herança é mal: a falha épica do DataAnnotationsModelBinder , percorre um exemplo disso em C #. Ele mostra o uso da inheritance quando a composição deveria ter sido usada e como ela poderia ser refatorada.

Em Java ou C #, um object não pode alterar seu tipo depois de ter sido instanciado.

Portanto, se seu object precisar aparecer como um object diferente ou se comportar de maneira diferente dependendo do estado ou das condições de um object, use Composition : consulte State and Strategy Design Patterns.

Se o object precisar ser do mesmo tipo, use as interfaces Herança ou Implementar.

Pessoalmente eu aprendi a preferir sempre composição sobre inheritance. Não há nenhum problema programático que você possa resolver com inheritance que você não pode resolver com composição; embora você possa ter que usar Interfaces (Java) ou Protocols (Obj-C) em alguns casos. Como o C ++ não sabe nada disso, você terá que usar classs base abstratas, o que significa que você não pode se livrar da inheritance em C ++.

A composição é geralmente mais lógica, fornece melhor abstração, melhor encapsulamento, melhor reutilização de código (especialmente em projetos muito grandes) e é menos provável que quebre algo à distância apenas porque você fez uma alteração isolada em qualquer parte do código. Também torna mais fácil defender o ” Princípio da Responsabilidade Única “, que geralmente é resumido como ” Nunca deve haver mais de um motivo para uma class mudar “, e isso significa que toda class existe para um propósito específico e deveria só tem methods que estão diretamente relacionados ao seu propósito. Também ter uma tree de inheritance muito superficial torna muito mais fácil manter a visão geral mesmo quando o projeto começa a ficar muito grande. Muitas pessoas pensam que a inheritance representa bem o nosso mundo real , mas isso não é verdade. O mundo real usa muito mais composição do que inheritance. Quase todos os objects do mundo real que você pode segurar na sua mão foram compostos de outros objects menores do mundo real.

Há desvantagens da composição, no entanto. Se você ignorar completamente a inheritance e se concentrar apenas na composição, notará que muitas vezes precisará escrever algumas linhas de código extras que não seriam necessárias se tivesse usado inheritance. Você às vezes também é forçado a repetir-se e isso viola o princípio DRY (DRY = Don’t Repeat Yourself). Também a composição geralmente requer delegação, e um método está apenas chamando outro método de outro object sem nenhum outro código envolvendo esta chamada. Essas “chamadas de método duplo” (que podem facilmente se estender para chamadas de methods triplos ou quádruplos e até mais do que isso) têm um desempenho muito pior do que a inheritance, em que você simplesmente herda um método de seu pai. Chamar um método herdado pode ser tão rápido quanto chamar um não herdado, ou pode ser um pouco mais lento, mas geralmente ainda é mais rápido do que duas chamadas de método consecutivas.

Você deve ter notado que a maioria das linguagens OO não permite inheritance múltipla. Embora existam alguns casos em que várias inheritances podem realmente comprar algo para você, mas essas são exceções em vez da regra. Sempre que você topar com uma situação em que você acha que “inheritance múltipla seria um recurso muito legal para resolver esse problema”, você geralmente está em um ponto em que deveria repensar a inheritance, já que mesmo isso pode requerer algumas linhas de código extras , uma solução baseada na composição geralmente se tornará muito mais elegante, flexível e futura.

Herança é realmente um recurso legal, mas eu tenho medo de ter sido usado em excesso nos últimos dois anos. As pessoas tratavam a inheritance como o único martelo que pode pregar tudo, independentemente de ser realmente um prego, um parafuso ou talvez algo completamente diferente.

Não encontrei uma resposta satisfatória aqui, então escrevi uma nova.

Para entender por que ” preferimos composição sobre inheritance”, precisamos primeiro voltar a suposição omitida neste idioma encurtado.

Existem dois benefícios da inheritance: subtipagem e subsorting

  1. Subtipagem significa estar em conformidade com uma assinatura de tipo (interface), ou seja, um conjunto de APIs, e pode-se replace parte da assinatura para obter o polymorphism de subtipagem.

  2. Subsorting significa reutilização implícita de implementações de methods.

Com os dois benefícios vem dois propósitos diferentes para fazer inheritance: orientada para subtipação e orientada para reutilização de código.

Se a reutilização de código for o único propósito, a subclass pode dar mais do que o que ele precisa, ou seja, alguns methods públicos da class pai não fazem muito sentido para a class filha. Neste caso, em vez de favorecer a composição sobre a inheritance, a composição é exigida . É também de onde vem a noção “é-um” versus “tem-um”.

Então, apenas quando a subtipagem é proposta, ou seja, para usar a nova class mais tarde de uma maneira polimórfica, enfrentamos o problema de escolher inheritance ou composição. Essa é a suposição que é omitida no idioma abreviado em discussão.

Para subtipo é para se adequar a uma assinatura de tipo, isso significa que a composição sempre deve expor não menos quantidade de APIs do tipo. Agora, os trade-offs entram em ação:

  1. A inheritance fornece reutilização direta de código, se não for sobreposta, enquanto a composição tem que recodificar toda API, mesmo que seja apenas um simples trabalho de delegação.

  2. A inheritance fornece uma recursion aberta direta através do site polimórfico interno, isto é, invocando o método de substituição (ou mesmo o tipo ) em outra function-membro, pública ou privada (embora desencorajada ). A recursion aberta pode ser simulada via composição , mas requer esforço extra e nem sempre é viável (?). Esta resposta a uma pergunta duplicada fala algo semelhante.

  3. Herança expõe membros protegidos . Isso interrompe o encapsulamento da class pai e, se usado pela subclass, outra dependência entre o filho e seu pai é introduzida.

  4. A composição tem a capacidade de inversão de controle, e sua dependência pode ser injetada dinamicamente, como é mostrado no padrão de decorador e padrão de proxy .

  5. A composição tem o benefício da programação orientada por combinadores , ou seja, funciona de uma maneira semelhante ao padrão composto .

  6. A composição segue imediatamente a programação para uma interface .

  7. Composição tem o benefício de inheritance múltipla fácil.

Com os trade offs acima em mente, nós preferimos a composição sobre inheritance. No entanto, para classs fortemente relacionadas, ou seja, quando a reutilização de código implícita realmente traz benefícios, ou o poder mágico da recursion aberta é desejado, a inheritance será a escolha.

Minha regra geral: antes de usar a inheritance, considere se a composição faz mais sentido.

Motivo: Subsorting geralmente significa mais complexidade e conectividade, ou seja, mais difícil de mudar, manter e escalar sem cometer erros.

Uma resposta muito mais completa e concreta de Tim Boudreau da Sun:

Problemas comuns para o uso de inheritance como eu vejo são:

  • Atos inocentes podem ter resultados inesperados – O exemplo clássico disso são chamadas para methods substituíveis do construtor da superclass, antes que os campos da instância de subclasss tenham sido inicializados. Em um mundo perfeito, ninguém faria isso. Este não é um mundo perfeito.
  • Ele oferece tentações perversas para os subclasss fazerem suposições sobre a ordem das chamadas do método e tal – tais suposições tendem a não ser estáveis ​​se a superclass puder evoluir com o tempo. Veja também minha analogia de torradeira e cafeteira .
  • As classs ficam mais pesadas – você não necessariamente sabe qual trabalho sua superclass está fazendo em seu construtor, ou quanta memory ele vai usar. Então construir algum object inocente e leve pode ser muito mais caro do que você pensa, e isso pode mudar com o tempo se a superclass evoluir
  • Encoraja uma explosão de subclasss . A carga de aula custa tempo, mais aulas custam memory. Isso pode não ser um problema até que você esteja lidando com um aplicativo na escala do NetBeans, mas lá, tivemos problemas reais com, por exemplo, menus sendo lentos porque a primeira exibição de um menu acionou um carregamento de class massivo. Corrigimos isso mudando para uma syntax mais declarativa e outras técnicas, mas também custamos tempo para corrigir.
  • Isso torna mais difícil mudar as coisas mais tarde – se você tornou uma class pública, trocar a superclass é quebrar as subclasss – é uma escolha que, depois de tornar o código público, você é casado. Então, se você não está alterando a funcionalidade real para sua superclass, você terá muito mais liberdade para mudar as coisas mais tarde se usar, em vez de estender o que precisa. Tome, por exemplo, subclassificando JPanel – isso geralmente é errado; e se a subclass é pública em algum lugar, você nunca terá a chance de rever essa decisão. Se for acessado como JComponent getThePanel (), você ainda poderá fazê-lo (dica: expor modelos para os componentes dentro de como sua API).
  • Hierarquias de objects não escalam (ou fazê-las escalar mais tarde é muito mais difícil do que planejar com antecedência) – esse é o problema clássico de “muitas camadas”. Vou falar sobre isso abaixo e como o padrão AskTheOracle pode resolvê-lo (embora possa ofender os puristas da OOP).

Minha opinião sobre o que fazer, se você permitir a inheritance, o que você pode fazer com um grão de sal é:

  • Não exponha nenhum campo, exceto as constantes
  • Os methods devem ser abstratos ou finais
  • Não chame nenhum método do construtor da superclass

tudo isso se aplica menos a projetos pequenos do que grandes, e menos a classs privadas do que públicas

A inheritance é muito poderosa, mas você não pode forçá-la (veja: o problema círculo-elipse ). Se você realmente não pode ter certeza de um verdadeiro relacionamento de subtipo “é-um”, então é melhor ir com a composição.

A inheritance cria um forte relacionamento entre uma subclass e uma superclass; subclass deve estar ciente dos detalhes de implementação das superclasss. Criar a superclass é muito mais difícil, quando você precisa pensar em como ela pode ser estendida. Você tem que documentar cuidadosamente as invariantes de class e declarar quais methods os methods substituíveis usam internamente.

A inheritance às vezes é útil, se a hierarquia realmente representar um relacionamento é-um. Relaciona-se ao Princípio Aberto-Fechado, que afirma que as classs devem ser fechadas para modificação, mas abertas à extensão. Dessa forma você pode ter polymorphism; ter um método genérico que lide com o supertipo e seus methods, mas, por meio do despacho dynamic, o método da subclass é invocado. Isso é flexível e ajuda a criar a indireção, que é essencial no software (para saber menos sobre os detalhes da implementação).

A inheritance é facilmente usada em excesso e cria complexidade adicional, com dependencies complexas entre as classs. Também entender o que acontece durante a execução de um programa fica muito difícil devido a camadas e seleção dinâmica de chamadas de método.

Eu sugeriria usar a composição como padrão. É mais modular e oferece o benefício da binding tardia (você pode alterar o componente dinamicamente). Também é mais fácil testar as coisas separadamente. E se você precisa usar um método de uma class, você não é forçado a ser de certa forma (Princípio de Substituição Liskov).

Você precisa dar uma olhada no Princípio de Substituição de Liskov nos princípios SOLID de design de classs do Uncle Bob. 🙂

Suponha que uma aeronave tenha apenas duas partes: um motor e asas.
Então, existem duas maneiras de projetar uma class de aeronave.

 Class Aircraft extends Engine{ var wings; } 

Agora sua aeronave pode começar com asas fixas
e mudá-los para as asas rotativas na mosca. É essencialmente
um motor com asas. Mas e se eu quisesse mudar
o motor na mosca também?

O Engine class base expõe um mutador para alterar seu
propriedades, ou eu redesenho a Aircraft como:

 Class Aircraft { var wings; var engine; } 

Agora, eu posso replace o meu motor na mosca também.

“Preferir composição sobre inheritance” é um princípio de design, que diz que não abuse da inheritance quando não se encheckbox.

Se não existir uma relação hierárquica do mundo real entre duas entidades, não use inheritance, mas use composição. Composição representa o relacionamento “HAS A”.

Por exemplo, o carro tem rodas, corpo, motor, etc. Mas, se você herdar aqui, ele se tornará uma roda – o que é incorreto.

Para mais explicações, consulte preferir composição sobre inheritance

Por que preferir composição sobre inheritance?

Veja outras respostas.

Quando você deve escolher inheritance sobre composição?

Sempre que a frase “um Bar é um Foo e um Bar pode fazer tudo o que um Foo pode fazer” faz sentido.

A sabedoria convencional diz que se a frase “um Bar é um Foo” faz sentido, então é uma boa dica que escolher a inheritance é apropriado. Por exemplo, um cachorro é um animal, portanto, ter a class Dog herdada de Animal é provavelmente um bom design.

Infelizmente, esse simples teste “é-um” não é confiável. The Circle-Ellipse problem is a great counter-example: even though a circle is an ellipse, it is a bad idea to have the Circle class inherit from Ellipse, because there are things that ellipses can do but circles can’t. For example, ellipses can stretch, but circles can’t. So while you can have ellipse.stretch() , you cannot have circle.stretch() .

This is why a better test is “a Bar is a Foo, and a Bar can do everything that a Foo can do “. This truly means that Foo can be used polymorphically. The “is-a” test is only a necessary condition for polymorphic use, and typically means that all getters of Foo make sense in Bar. The additional “can-do-everything” test means that all setters of Foo also make sense in Bar. This additional test typically fails when a class Bar “is-a” Foo, but adds some constraints to it, in which case you should not use inheritance, because Foo could not be used polymorphically. In other words, inheritance is not about sharing properties, but about sharing functionality. Derived classs should extend the functionality of base classs, not restrict it.

This is equivalent to the Liskov Substitution Principle :

Functions that use pointers or references to base classs must be able to use objects of derived classs without knowing it

When you want to “copy”/Expose the base class’ API, you use inheritance. When you only want to “copy” functionality, use delegation.

One example of this: You want to create a Stack out of a List. Stack only has pop, push and peek. You shouldn’t use inheritance given that you don’t want push_back, push_front, removeAt, et al.-kind of functionality in a Stack.

These two ways can live together just fine and actually support each other.

Composition is just playing it modular: you create interface similar to the parent class, create new object and delegate calls to it. If these objects need not to know of each other, it’s quite safe and easy to use composition. There are so many possibilites here.

However, if the parent class for some reason needs to access functions provided by the “child class” for inexperienced programmer it may look like it’s a great place to use inheritance. The parent class can just call it’s own abstract “foo()” which is overwritten by the subclass and then it can give the value to the abstract base.

It looks like a nice idea, but in many cases it’s better just give the class an object which implements the foo() (or even set the value provided the foo() manually) than to inherit the new class from some base class which requires the function foo() to be specified.

Por quê?

Because inheritance is a poor way of moving information .

The composition has a real edge here: the relationship can be reversed: the “parent class” or “abstract worker” can aggregate any specific “child” objects implementing certain interface + any child can be set inside any other type of parent, which accepts it’s type . And there can be any number of objects, for example MergeSort or QuickSort could sort any list of objects implementing an abstract Compare -interface. Or to put it another way: any group of objects which implement “foo()” and other group of objects which can make use of objects having “foo()” can play together.

I can think of three real reasons for using inheritance:

  1. You have many classs with same interface and you want to save time writing them
  2. You have to use same Base Class for each object
  3. You need to modify the private variables, which can not be public in any case

If these are true, then it is probably necessary to use inheritance.

There is nothing bad in using reason 1, it is very good thing to have a solid interface on your objects. This can be done using composition or with inheritance, no problem – if this interface is simple and does not change. Usually inheritance is quite effective here.

If the reason is number 2 it gets a bit tricky. Do you really only need to use the same base class? In general, just using the same base class is not good enough, but it may be a requirement of your framework, a design consideration which can not be avoided.

However, if you want to use the private variables, the case 3, then you may be in trouble. If you consider global variables unsafe, then you should consider using inheritance to get access to private variables also unsafe . Mind you, global variables are not all THAT bad – databases are essentially big set of global variables. But if you can handle it, then it’s quite fine.

Aside from is a/has a considerations, one must also consider the “depth” of inheritance your object has to go through. Anything beyond five or six levels of inheritance deep might cause unexpected casting and boxing/unboxing problems, and in those cases it might be wise to compose your object instead.

A simple way to make sense of this would be that inheritance should be used when you need an object of your class to have the same interface as its parent class, so that it can thereby be treated as an object of the parent class (upcasting). Moreover, function calls on a derived class object would remain the same everywhere in code, but the specific method to call would be determined at runtime (ie the low-level implementation differs, the high-level interface remains the same).

Composition should be used when you do not need the new class to have the same interface, ie you wish to conceal certain aspects of the class’ implementation which the user of that class need not know about. So composition is more in the way of supporting encapsulation (ie concealing the implementation) while inheritance is meant to support abstraction (ie providing a simplified representation of something, in this case the same interface for a range of types with different internals).

When you have an is-a relation between two classs (example dog is a canine), you go for inheritance.

On the other hand when you have has-a or some adjective relationship between two classs (student has courses) or (teacher studies courses), you chose composition.

Subtyping is appropriate and more powerful where the invariants can be enumerated , else use function composition for extensibility.

I agree with @Pavel, when he says, there are places for composition and there are places for inheritance.

I think inheritance should be used if your answer is an affirmative to any of these questions.

  • Is your class part of a structure that benefits from polymorphism ? For example, if you had a Shape class, which declares a method called draw(), then we clearly need Circle and Square classs to be subclasss of Shape, so that their client classs would depend on Shape and not on specific subclasss.
  • Does your class need to re-use any high level interactions defined in another class ? The template method design pattern would be impossible to implement without inheritance. I believe all extensible frameworks use this pattern.

However, if your intention is purely that of code re-use, then composition most likely is a better design choice.

A rule of thumb I have heard is inheritance should be used when its a “is-a” relationship and composition when its a “has-a”. Even with that I feel that you should always lean towards composition because it eliminates a lot of complexity.

Inheritance is a very powerfull machanism for code reuse. But needs to be used properly. I would say that inheritance is used correctly if the subclass is also a subtype of the parent class. As mentioned above, the Liskov Substitution Principle is the key point here.

Subclass is not the same as subtype. You might create subclasss that are not subtypes (and this is when you should use composition). To understand what a subtype is, lets start giving an explanation of what a type is.

When we say that the number 5 is of type integer, we are stating that 5 belongs to a set of possible values (as an example, see the possible values for the Java primitive types). We are also stating that there is a valid set of methods I can perform on the value like addition and subtraction. And finally we are stating that there are a set of properties that are always satisfied, for example, if I add the values 3 and 5, I will get 8 as a result.

To give another example, think about the abstract data types, Set of integers and List of integers, the values they can hold are restricted to integers. They both support a set of methods, like add(newValue) and size(). And they both have different properties (class invariant), Sets does not allow duplicates while List does allow duplicates (of course there are other properties that they both satisfy).

Subtype is also a type, which has a relation to another type, called parent type (or supertype). The subtype must satisfy the features (values, methods and properties) of the parent type. The relation means that in any context where the supertype is expected, it can be substitutable by a subtype, without affecting the behaviour of the execution. Let’s go to see some code to exemplify what I’m saying. Suppose I write a List of integers (in some sort of pseudo language):

 class List { data = new Array(); Integer size() { return data.length; } add(Integer anInteger) { data[data.length] = anInteger; } } 

Then, I write the Set of integers as a subclass of the List of integers:

 class Set, inheriting from: List { add(Integer anInteger) { if (data.notContains(anInteger)) { super.add(anInteger); } } } 

Our Set of integers class is a subclass of List of Integers, but is not a subtype, due to it is not satisfying all the features of the List class. The values, and the signature of the methods are satisfied but the properties are not. The behaviour of the add(Integer) method has been clearly changed, not preserving the properties of the parent type. Think from the point of view of the client of your classs. They might receive a Set of integers where a List of integers is expected. The client might want to add a value and get that value added to the List even if that value already exist in the List. But her wont get that behaviour if the value exists. A big suprise for her!

This is a classic example of an improper use of inheritance. Use composition in this case.

(a fragment from: use inheritance properly ).

Composition v/s Inheritance is a wide subject. There is no real answer for what is better as I think it all depends on the design of the system.

Generally type of relationship between object provide better information to choose one of them.

If relation type is “IS-A” relation then Inheritance is better approach. otherwise relation type is “HAS-A” relation then composition will better approach.

Its totally depend on entity relationship.

To address this question from a different perspective for newer programmers:

Inheritance is often taught early when we learn object-oriented programming, so it’s seen as an easy solution to a common problem.

I have three classs that all need some common functionality. So if I write a base class and have them all inherit from it, then they will all have that functionality and I’ll only need to maintain it in once place.

It sounds great, but in practice it almost never, ever works, for one of several reasons:

  • We discover that there are some other functions that we want our classs to have. If the way that we add functionality to classs is through inheritance, we have to decide – do we add it to the existing base class, even though not every class that inherits from it needs that functionality? Do we create another base class? But what about classs that already inherit from the other base class?
  • We discover that for just one of the classs that inherits from our base class we want the base class to behave a little differently. So now we go back and tinker with our base class, maybe adding some virtual methods, or even worse, some code that says, “If I’m inherited type A, do this, but if I’m inherited type B, do that.” That’s bad for lots of reasons. One is that every time we change the base class, we’re effectively changing every inherited class. So we’re really changing class A, B, C, and D because we need a slightly different behavior in class A. As careful as we think we are, we might break one of those classs for reasons that have nothing to do with those classs.
  • We might know why we decided to make all of these classs inherit from each other, but it might not (probably won’t) make sense to someone else who has to maintain our code. We might force them into a difficult choice – do I do something really ugly and messy to make the change I need (see the previous bullet point) or do I just rewrite a bunch of this.

In the end, we tie our code in some difficult knots and get no benefit whatsoever from it except that we get to say, “Cool, I learned about inheritance and now I used it.” That’s not meant to be condescending because we’ve all done it. But we all did it because no one told us not to.

As soon as someone explained “favor composition over inheritance” to me, I thought back over every time I tried to share functionality between classs using inheritance and realized that most of the time it didn’t really work well.

The antidote is the Single Responsibility Principle . Think of it as a constraint. My class must do one thing. I must be able to give my class a name that somehow describes that one thing it does. (There are exceptions to everything, but absolute rules are sometimes better when we’re learning.) It follows that I cannot write a base class called ObjectBaseThatContainsVariousFunctionsNeededByDifferentClasses . Whatever distinct functionality I need must be in its own class, and then other classs that need that functionality can depend on that class, not inherit from it.

At the risk of oversimplifying, that’s composition – composing multiple classs to work together. And once we form that habit we find that it’s much more flexible, maintainable, and testable than using inheritance.

As many people told, I will first start with the check – whether there exists an “is-a” relationship. If it exists I usually check the following:

Whether the base class can be instantiated. That is, whether the base class can be non-abstract. If it can be non-abstract I usually prefer composition

Eg 1. Accountant is an Employee. But I will not use inheritance because a Employee object can be instantiated.

Eg 2. Book is a SellingItem. A SellingItem cannot be instantiated – it is abstract concept. Hence I will use inheritacne. The SellingItem is an abstract base class (or interface in C#)

What do you think about this approach?

Also, I support @anon answer in Why use inheritance at all?

The main reason for using inheritance is not as a form of composition – it is so you can get polymorphic behaviour. If you don’t need polymorphism, you probably should not be using inheritance.

@MatthieuM. says in https://softwareengineering.stackexchange.com/questions/12439/code-smell-inheritance-abuse/12448#comment303759_12448

The issue with inheritance is that it can be used for two orthogonal purposes:

interface (for polymorphism)

implementation (for code reuse)

REFERÊNCIA

  1. Which class design is better?
  2. Inheritance vs. Aggregation

Even though Composition is preferred, I would like to highlight pros of Inheritance and cons of Composition .

Pros of Inheritance:

  1. It establishes a logical ” IS A” relation. If Car and Truck are two types of Vehicle ( base class), child class IS A base class.

    ou seja

    Car is a Vehicle

    Truck is a Vehicle

  2. With inheritance, you can define/modify/extend a capability

    1. Base class provides no implementation and sub-class has to override complete method (abstract) => You can implement a contract
    2. Base class provides default implementation and sub-class can change the behaviour => You can re-define contract
    3. Sub-class adds extension to base class implementation by calling super.methodName() as first statement => You can extend a contract
    4. Base class defines structure of the algorithm and sub-class will override a part of algorithm => You can implement Template_method without change in base class skeleton

Cons of Composition:

  1. In inheritance, subclass can directly invoke base class method even though it’s not implementing base class method because of IS A relation. If you use composition, you have to add methods in container class to expose contained class API

eg If Car contains Vehicle and if you have to get price of the Car , which has been defined in Vehicle , your code will be like this

 class Vehicle{ protected double getPrice(){ // return price } } class Car{ Vehicle vehicle; protected double getPrice(){ return vehicle.getPrice(); } }