Effective Java 2nd Edition, Item 16: Favor composition over inheritance:
Inheritance is appropriate only in circumstances where the subclass really is a subtype of the superclass. In other words, a class B should only extend a class A only if an “is-a” relationship exists between the two classes. If you are tempted to have a class B extend a class A, ask yourself this question: Is every B really an A? If you cannot truthfully answer yes to this question, B should not extend A. If the answer is no, it is often the case that B should contain a private instance of A and expose a smaller and simpler API; A is not an essential part of B, merely a detail of its implementation.
There are a number of obvious violations of this principle in the Java platform libraries. For example, a stack is not a vector, so
Stack
should not extendVector
. Similarly, a property list is not a hash table, soProperties
should not extendHashtable
. In both cases, composition would have been preferrable.
The book goes in greater detail, and combined with Item 17: Design and document for inheritance or else prohibit it, advises against overuse and abuse of inheritance in your design.
Here’s a simple example that shows the problem of Stack
allowing un-Stack
-like behavior:
Stack<String> stack = new Stack<String>();
stack.push("1");
stack.push("2");
stack.push("3");
stack.insertElementAt("squeeze me in!", 1);
while (!stack.isEmpty()) {
System.out.println(stack.pop());
}
// prints "3", "2", "squeeze me in!", "1"
This is a gross violation of the stack abstract data type.
See also
- Wikipedia/Stack (data structure)
In computer science, a stack is a last in, first out (LIFO) abstract data type and data structure.