Technically, the differences aren't really significant but, conceptually, they are entirely different things and that leads to the technical differences others have mentioned.
An abstract superclass is exactly what it sounds like, it's a common type that is shared by many other types, like Cats and Dogs are Animals.
An interface is also exactly what it sounds like, it's an interface through which other classes can communicate with the object. If you want to make a Cat Walk, you're ok, cause Cat implements a CanWalk interface. Same for a Lizard, though they walk very differently. A Snake, on the other hand, does not implement CanWalk, so you can't tell it to Walk. Meanwhile, Lizard and Snake (or possibly more explicit subclasses -- I'm not an expert) might both shed their skin, and thus implement CanShed, while a Cat couldn't do that.
But they're all still Animals and have some common properties, like whether they're alive or dead.
This is why all methods on an interface must be implemented as public (or explicitly, in C#). Cause what's the point in an interface that's hidden from the class interfacing with the object? It's also why you can have multiple interfaces to an object, even when a language doesn't support multiple inheritance.
To go back to your question, when you look at it this way, there's very rarely a reason to have an entirely abstract superclass.
A good motivating example for default methods is in the Java standard library, where you now have
list.sort(ordering);
instead of
Collections.sort(list, ordering);
I don't think they could have done that otherwise without more than one identical implementation of List.sort
.
Best Answer
OOP has composition and substitution.
C++ has multiple inheritance, template specialisation, embedding and value/move/pointer semantics.
Java has single inheritance and interfaces, embedding and reference semantics.
The common way the OOP school uses these languages is to employ inheritance for object substitution and embedding for composition. But you also need a common ancestor and a way to runtime-cast (in C++ is called
dynamic_cast
, in Java is just asking an interface from another).Java does all this by its own
java.lang.Object
rooted hierachy. C++ doesn't have a predefined common root, so you should at least define it, to come to a same "picture" (but this is limiting some C++ possibilities...).After that, the possibility to have compile-time polymorphism (think to CRTP) and value semantic can offer also other alternatives to the way the concept of "OOP object" can be ported into a C++ program.
You can even imagine the heresy to use embedding and implicit conversion to manage substitution and private inheritance to manage composition, in fact inverting the traditional school paradigm. (Of course, this way is 20 years younger than the other, so don't expect a wide community support in doing that)
Or you can imagine a virtual common base to all classes, form interface (no implementation) to final classes (fully implemented) going through partially implemented interfaces an even interface clusters, using "dominance" as dispatching from interface to implementations through a "multi stacked-parallelogram" inheritance scheme.
Comparing OOP to java to C++ assuming there is just one and only OOP way is limiting the capabilities of both the languages.
Forcing C++ to strictly adhere to Java coding idioms is denaturating C++ as forcing Java to behave as a C++-like language is denaturating Java.
Is not a matter of "sensibility" but of different "aggregation mechanisms" the two languages have and different way to combine them that makes some idiom more profitable in one language than the other and vice versa.