Most design patten books say we should "Favor object composition over class inheritance."
But can anyone give me an example that inheritance is better than object composition.
Most design patten books say we should "Favor object composition over class inheritance."
But can anyone give me an example that inheritance is better than object composition.
Inheritance is appropriate for is-a
relationships. It is a poor fit for has-a
relationships.
Since most relationships between classes/components fall into the has-a
bucket (for example, a Car
class is likely not a HashMap
, but it may have a HashMap
), it then follows the composition is often a better idea for modeling relationships between classes rather than inheritance.
This is not to say however that inheritance is not useful or not the correct solution for some scenarios.
My simple answer is that you should use inheritance for behavioral purposes. Subclasses should override methods to change the behaviour of the method and the object itself.
This article (interview with Erich Gamma, one of the GoF) elaborates clearly why Favor object composition over class inheritance.
Just think of it as having an "is-a" or a "has-a" relationship
In this example Human "is-a" Animal, and it may inherits different data from the Animal class. Therefore Inheritance is used:
abstract class Animal {
private String name;
public String getName(){
return name;
}
abstract int getLegCount();
}
class Dog extends Animal{
public int getLegCount(){
return 4;
}
}
class Human extends Animal{
public int getLegCount(){
return 2;
}
}
Composition makes sense if one object is the owner of another object. Like a Human object owning a Dog object. So in the following example a Human object "has-a" Dog object
class Dog{
private String name;
}
class Human{
private Dog pet;
}
hope that helped...
It is a fundamental design principle of a good OOD. You can assign a behaviour to a class dynamicly "in runtime", if you use composition in your design rather than inheritance like in Strategy Pattern. Say,
interface Xable {
doSomething();
}
class Aable implements Xable { doSomething() { /* behave like A */ } }
class Bable implements Xable { doSomething() { /* behave like B */ } }
class Bar {
Xable ability;
public void setAbility(XAble a) { ability = a; }
public void behave() {
ability.doSomething();
}
}
/*now we can set our ability in runtime dynamicly */
/*somewhere in your code */
Bar bar = new Bar();
bar.setAbility( new Aable() );
bar.behave(); /* behaves like A*/
bar.setAbility( new Bable() );
bar.behave(); /* behaves like B*/
if you did use inheritance, the "Bar" would get the behaviour "staticly" over inheritance.
Inheritance allows an object of the derived type to be used in nearly any circumstance where one would use an object of the base type. Composition does not allow this. Use inheritance when such substitution is required, and composition when it is not.
In Java, whenever you inherit from a class, your new class also automatically becomes a subtype of the original class type. Since it is a subtype, it needs to adhere to the Liskov substitution principle.
This principle basically says that you must be able to use the subtype anywhere where the supertype is expected. This severely limits how the behavior of your new inherited class can differ from the original class.
No compiler will be able to make you adhere to this principle though, but you can get in trouble if you don't, especially when other programmers are using your classes.
If you were programming in a language that allows subclassing without subtyping, the rule "Favor object composition over inheritance" wouldn't be as important as it is in languages like Java or C#.
Inheritance is necessary for subtyping. Consider:
class Base {
void Foo() { /* ... */ }
void Bar() { /* ... */ }
}
class Composed {
void Foo() { mBase.Foo(); }
void Bar() { mBase.Foo(); }
private Base mBase;
}
Even though Composed
supports all of the methods of Foo
it cannot be passed to a function that expects a value of type Foo
:
void TakeBase(Base b) { /* ... */ }
TakeBase(new Composed()); // ERROR
So, if you want polymorphism, you need inheritance (or its cousin interface implementation).