Interface inheritance vs Implementation inheritance
Implementation inheritance is a relationship where a child class inherits behaviour implementation from a base class.
Interface inheritance is when a child class only inherits the description of behaviour from the base class and provides the implementation itself.
The concept of preferring interface inheritance probably came first from the C++ and COM programming days, where an abstract class would be used to define methods in a base class and the inheriting classes would be required to implement the methods. Java provides with the concept of interfaces which essentially provide the same pattern for implementation.
So why prefer interface inheritance to implementation inheritance? The simple answer to this is to avoid coupling between two components of an application.
Coupling
Lets consider the case of application logging in Java. There are various implementations for logging viz., log4j, java.util.logging, logback. If an application was written with log4j and now needs to be moved to logback, for example, it would be a lot of work to change logging statements throughout the code base. This is where slf4j framework helps, by providing an abstract layer for applications. The consumer application only needs to use Logger interface for logging in the application. The underlying concrete implementation of logging can be switched easily from log4j to logback or java.util.logging. So by using a higher level of abstraction, the application gets the flexibility to switch implementations without changing the code of the application.
Fragile base class problem
The fragile base class problem can be viewed as a type of coupling problem. It points to an architectural flaw with implementation inheritance where a change in a base class may require recompiling, reimplementation and retesting of the child classes. This makes the base class fragile to changes.
A simple example would be if the base class needs to change the return type of a method from List to Set. To accommodate the change, all child classes and their client classes would need to be modified and retested. This could be avoided by using a higher level of abstraction for the return type such as Collection in Java.
The other problem that can cause infinite recursion is when we have method1 in the base class calling method2 and the child class overrides the method2 and makes a call to method1. At runtime a call to the child class' method2 implementation causes an infinite recursion until the program crashes with a stack overflow error.
This article is good summary of pre-java-8 inheritance. AfterJava 8 introduced default interface method, it seems we need to revisit some of the ideas. Understand this article may not for Java only and a few years old. The two terms "interface inheritance" and "implementation inheritance" is for general OO design. In Java they are "interface/class...extends", and "implementation inheritance" could mean: 1. "class ... extends" and 2. "class implements interface". Fragile base class and potential looping between super and sub classes largely due to case 1 "class inheritance" using "class...extends" in Java. There is no base class fragile issue with 2. "class implements interface". Also Oracle/Sun Java team has done a wonderful job to use interface default method to avoid base class fragile issue mentioned above. To avoid impact for the whole Java community to refactor Collection Hierarchy Tree in Java, Java moved default method implementation like stream() to the very "base" interface of Collection. It seems introduced an anti-pattern to the general OOP community prefers interface to implementation inheritance. The implementation inheritance seems a plus for code-reuse, but a burden for future change.
good explanation