Inheritance Breaks Encapsulation
When you publish an interface with inheritance permitted, you substantially increase the size of your interface. Specifically, instead of just your public methods being public, all of your calls to your public methods are public. Here is a real (simplified) example from the java collections framework, courtesy of Peter Norvig (http://norvig.com/java-iaq.html).
Public Class HashTable{
...
Public Object put(K key, V value){
try{
//add object to table;
}catch(TableFullException e){
increaseTableSize();
put(key,value);
}
}
}
So what happens if we subclass this?
/** A version of Hashtable that lets you do
* table.put("dog", "canine");, and then have
* table.get("dogs") return "canine". **/
public class HashtableWithPlurals extends Hashtable {
/** Make the table map both key and key + "s" to value. **/
public Object put(Object key, Object value) {
super.put(key + "s", value);
return super.put(key, value);
}
}
We have a bug: Occasionally we add "dog" and the hashtable gets an entry for "dogss". The cause was someone providing an implementation of put that the person designing the Hashtable class did not expect.
Note that this is not a problem with recursion, this can happen any time that a class calls one of its own public methods. In reality, there may well be several levels of inheritance involved in the problem.
This can be resolved by committing to not call the public methods of a class in that class. In practice, this commitment is frequently not honoured and is a major reason why object oriented code is considered "brittle".
Inheritance Breaks Extensibility
If you allow your class to be subclassed, you are committing to not add any methods to your class. This could otherwise be done without breaking anything.
When you add new methods to an interface, anyone who has inherited from your class will need to implement those methods.