There are two fundamental mechanisms for building new classes from existing ones: inheritance and aggregation
Other definition: One class can use features from another class to extend its functionality (an “Is a” relationship) i.e., a Car is a Automobile.
Inheritance is the inclusion of behaviour (i.e. methods) and state (i.e. variables) of a base class in a derived
class so that they are accessible in that derived class. The key benefit of Inheritance is that it provides the formal mechanism for code reuse.
The ‘is a’ relationship is expressed with inheritance and ‘has a’ relationship is expressed with composition. Both inheritance and composition allow you to place sub-objects inside your new class. Two of the main techniques for code reuse are class inheritance and object composition.
Inheritance is uni-directional. For example Car is a Vehicle. But Vehicle is not a Car. Inheritance uses extends key word. Composition: is used when Car has a Engine. It is incorrect to say Car is a
Engine. Composition simply means using instance variables that refer to other objects. The class Car will have an instance variable, which refers to a Engine object.
1. Implementation inheritance (aka class inheritance)
2. Interface inheritance (aka type inheritance)
Which one to use?
Prefer interface inheritance to implementation inheritance because it promotes the design
concept of coding to an interface and reduces coupling. Interface inheritance can achieve code reuse with the help of object composition. If you look at Gang of Four (GoF) design patterns, you can see that it favours interface inheritance to implementation inheritance.
“Wiki” definition: “object composition (not to be confused with function composition) is a way to combine simple objects or data types into more complex ones.”
Other definition: Allowing a class to contain object instances in other classes so they can be used to perform actions related to the class (an “has a” relationship) i.e., a person has the ability to walk.
As we know, inheritance gives us an ‘is-a’ relationship. To make the understanding of composition easier, we can say that composition gives us a ‘part-of’ relationship. Composition is shown on a UML diagram as a filled diamond.
If we were going to model a car, it would make sense to say that an engine is part-of a car. Within composition, the lifetime of the part (Engine) is managed by the whole (Car), in other words, when Car is destroyed, Engine is destroyed along with it.
. . .
The guide is that inheritance should be only used when subclass ‘is a’ superclass.
- Don’t use inheritance just to get code reuse. If there is no ‘is a’ relationship then use composition for code reuse. Overuse of implementation inheritance (uses the “extends” key word) can break all the subclasses, if the superclass is modified.
- Do not use inheritance just to get polymorphism. If there is no ‘is a’ relationship and all you want is polymorphism then use interface inheritance with composition, which gives you code reuse
relationship where a part CAN exist without a whole.
Just like composition, aggregation occurs when an object is composed of multiple objects. However, with composition, the internal objects (such as Tyre , Seat and Engine ) are owned by the main object ( Car ). If you destroy the Car , you also likely want the Tyre , Seat and Engine instances destroyed because they are a composition which, together, form a single Car.
Car ford = new Car(driver);