Inheritance or composition: Rely on is-a and has-a ?
No - "is a" does not always lead to inheritence. A well cited example is the relationship between a square and a rectangle. A square is a rectangle, but it will be bad to design code that inherits a Square class off a Rectangle class.
My suggestion is to enhance your "is a / has a" heuristic with the Liskov Substitution Principle. To check whether an inheritence relationship complies with the Liskov Substitution Principle, ask whether clients of a base class can operate on the sub class without knowing that it is operating on a sub class. Of course, all the properties of the sub class must be preserved.
In the square / rectangle example, we must ask whether a client of rectangle can operate on a square without knowing that it is a square. All that the client must know is that it is operating on a rectangle. The following function demonstrates a client that assumes that setting the width of a rectangle leaves the height unchanged.
void g(Rectangle& r)
{
r.SetWidth(5);
r.SetHeight(4);
assert(r.GetWidth() * r.GetHeight()) == 20);
}
This assumption is true for a rectangle, but not for a square. So the function cannot operate on a square and therefore the inheritence relationship violates the Liskov Substitution principle.
Other examples
What is the difference between IS -A relationship and HAS-A relationship in Java?
An IS-A relationship is inheritance. The classes which inherit are known as sub classes or child classes. On the other hand, HAS-A relationship is composition.
In OOP, IS-A relationship is completely inheritance. This means, that the child class is a type of parent class. For example, an apple is a fruit. So you will extend fruit to get apple.
class Apple extends Fruit {
}
On the other hand, composition means creating instances which have references to other objects. For example, a room has a table.
So you will create a class room and then in that class create an instance of type table.
class Room {
Table table = new Table();
}
A HAS-A relationship is dynamic (run time) binding while inheritance is a static (compile time) binding.
If you just want to reuse the code and you know that the two are not of same kind use composition. For example, you cannot inherit an oven from a kitchen. A kitchen HAS-A oven.
When you feel there is a natural relationship like Apple is a Fruit use inheritance.
Difference between Inheritance and Composition
They are absolutely different. Inheritance is an "is-a" relationship. Composition is a "has-a".
You do composition by having an instance of another class C
as a field of your class, instead of extending C
. A good example where composition would've been a lot better than inheritance is java.util.Stack
, which currently extends java.util.Vector
. This is now considered a blunder. A stack "is-NOT-a" vector; you should not be allowed to insert and remove elements arbitrarily. It should've been composition instead.
Unfortunately it's too late to rectify this design mistake, since changing the inheritance hierarchy now would break compatibility with existing code. Had Stack
used composition instead of inheritance, it can always be modified to use another data structure without violating the API.
I highly recommend Josh Bloch's book Effective Java 2nd Edition
- Item 16: Favor composition over inheritance
- Item 17: Design and document for inheritance or else prohibit it
Good object-oriented design is not about liberally extending existing classes. Your first instinct should be to compose instead.
See also:
- Composition versus Inheritance: A Comparative Look at Two Fundamental Ways to Relate Classes
java IS-A relationship exam question confusion
Your rationale is slightly off, as this relationship applies to classes, not to objects.
A string IS-A object since String
inherits from Object
. Similarly a FileOutputStream
IS-A OutputStream
IS-A Object
.
IS-A is a relationship between classes, no between classes and objects.
Inheritance vs Composition: Does composition effectively solve dependency issues? [Effective Java]
Ok so I looked up what @LeiYang recommended and came to realize the my question wasn't valid. The given paragraph states "a subclass depends on the implementation details of its superclass for its proper function" - which Object Composition would have no problem with, as it merely makes use of provided methods as is(without overriding). Therefore Object Composition
doesn't violate encapsulation and is relatively stable compared to Inheritance
.
Using both Inheritance and Composition in the same class?
They are not mutually exclusive. Example: Boat
and Sailboat
. Sailboat
is-a Boat
, but it has-a Sail
, which other Boat
s may or may not have.
Related Topics
C++ Reading the Data Part of a Wav File
How Much Footprint Does C++ Exception Handling Add
Will Casting Around Sockaddr_Storage and Sockaddr_In Break Strict Aliasing
Inheritance or Composition: Rely on "Is-A" and "Has-A"
Most Efficient/Elegant Way to Clip a Number
Specify Template Parameters at Runtime
Why Does a Std::Atomic Store with Sequential Consistency Use Xchg
Qml and C++ Image Interoperability
How to Change String into Qstring
How to Get a List of Files in a Directory in C++
When to Use Std::Begin and Std::End Instead of Container Specific Versions
(Partially) Specializing a Non-Type Template Parameter of Dependent Type
Std::To_String - More Than Instance of Overloaded Function Matches the Argument List
C++ Undefined Reference to Vtable and Inheritance