To provide some context, I've seen some comments lately that equate inheriting behavior from a supertype, with inheriting a pure interface with no behavior. But there are pretty significant, and different, consequences to each.
e.g. Here's a sample base class, and a "pure" interface (pseudocode):
class FlyingBird {
void fly() {
change state due to flight
}
}
interface Flyable {
void fly();
}
Now Let's say I have Swan and Dove. I'll subclass Swan from FlyingBird, and have Dove implement Flyable.
Swan extends FlyingBird {
(no defnition for fly, because we inherit it from FlyingBird)
}
Dove implements Flyable {
void fly() {
... must provide implementation for fly, because the interface only provides the signature
}
Now, I can call both swan.fly() and dove.fly(), but swan gets its implementation from FlyingBird. The idiom "Favor composition over inheritance" tells me to favor the Dove implementation over Swan, with some sort of injected implementation, but "subtype polymorphism" doesn't seem to make that distinction.
The distinction is important, because, for example:
There's a growing movement in OO to make classes "final" or "non-extendable" by default, because of the complexities of inheriting behavior without breaking the super-classes' semtantics. In other words, some people are suggesting that one form of subtype prototyping should be disabled by default. (I haven't heard anyone suggest getting rid of interfaces in Java.)
"Favor composition over inheritance" differentiates sharing behavior through class inheritance vs. providing a common interface backed by a shared implementation.
In other words, there are practical and important differences between inheriting behavior and just inheriting an interface.
Does subtype polymorphism distinguish between inheriting behavior, or inheriting an interface?