A class shall be either (conceptually) final or abstract

You know peaches? You know nectarines? Good, after you are back from Wikipedia we can continue. You know perhaps people who don’t like peaches; my father used to joke that for them peaches are shaved - I didn’t believe him despite of my young age.

The reasoning of the developer is as naive: “A nectarine is a shaved peach.” Hey, it says “is a” thus it is a specialization of peach and they merrily write

class Nectarine extends Peach

Another developer thinks he is even more clever, he says: “A peach is a nectarine with hairs, I just have to shave it”

class Peach extends Nectarine {

Nectarine shave();

}

If you read the article linked above you know that the correct(?) model is:

abstract class PeachTreeFruit {

enum Skin { Fuzzy, Smooth}
abstract Skin skin();

}

class Peach extends PeachTreeFruit {

Skin skin() { return Fuzzy;}

}

The definition of Nectarine is left as an exercise; this models closely what we need: A peach tree can give you both and they are siblings in the inheritance hierachy.

Let’s kill first the “conceptually”: As I don’t know of any subclass of Peach I am tempted to declare it final. The type Peach is complete (at the moment) and ready to use. We don’t care if the peach we buy is “freestone” or “clingstone”, but making the type final now is perhaps an overkill. Anyway as soon as we need FreeStone we should not derive simply from Peach without making it abstract.

This is the second common error with inheritance: If we say simply

FreeStonePeach extends Peach implements FreeStone

we say implicity: If it is not FreeStone it must be ClingStone. But this isn’t what we said when defining Peach. We are inferring properties to the superclass just by adding a subclass. The problem is that this works too well, but now any module that creates just a Peach now creates a ClingStone for modules that know about FreeStonePeach, mostly this goes along with the following refactoring when extending Peach:

Any method from FreeStone goes also to Peach to provide “default” behavior. So that we really have FreeStone extends AnyStone and Peach implements AnyStone. Lot of redundancy, but where is the problem?

The problem bites you in the back when genetic engineering will succeed in creating stoneless peaches. There are even two problems: First where to place out StoneLessPeach? Is it “better” than FreeStone or just something else? When facing this extension task multiple times the new class might be added non-consistently thus creating a maintenance problem, but this is long down the road and perhaps a SEP. The direct problem is posed by the AnyStone methods. As they are already defined in the non-abstract base-class, your are virtually 100% ensured that the developer will only override the methods he thinks are really important and perhaps take the one or other short by calling the super method. These design don’t last long, but still long enough to introduce subtle bugs.
Using all classes if they were either abstract or final is a safety net for the low-level design. Even if it is low-level: refactoring later can get quite expensive. The code is not consistent and the refactoring will pose the question which behavior is the desired one. So you don’t have a truw refactoring anymore and you might introduce new bugs. You also pay a price for frustating debugger sessions where developers try to understand a convoluted inheritance with lost of overrides and super calls.

Back to the orignal question: How to tell if you have a “is a” and which dierection. It is important to know that if you can switch sides it is neither of it. The point that resovlse the contradiction is the model we have with PeachTreeFruit: a peach and a nectarine are a PeachTeeFruit, so the original reasoning have to be rewritten to

“A nectarine is a peach-tree fruit with a smooth skin.”

and

“A peach is a peach-tree fruit with a fuzzy skin.”

Note that with this definition the ridiculous idea of shaving peaches doesn’t make any sense anymore. Myth busted.

Degenerated hierarchies

A related problem are degenerated hierarchies:

abstract class StatefulList extends List implements Stateful

abstract class PersistentList extends StatefulList implements Persistable

Why not collapsing both intermediary classes into one? The obvious reason is that you might want Statefuls that aren’t Persistable, but can there be Persistables that aren’t Stateful? The answer here was “no” as the implementation of PersistentList uses the Stateful interface. This all justifies having two classes and even if there is no other use of StatefulList it stays a good idea to separate the functionality into to distinct classes: The code for PersistentList calls some methods from Stateful and this makes clear where the code for persistence ends and where the control goes over to an other interface. It is simply harder to mangle everything into a large code-block that does everything without clear repsonibilties. This decomposition works only for classes that have dierected dependencies. If we had two interfaces Vegetables and Meat for the implementation Menu:

class Menu implements Vegetable, Meat

It is ridiculous to define

abstract class MeatMenu implements Meat

class Menu extends MeatMenu implements Vegetable

because you could delibarately define

abstract class VeggieMenu implements Vegetable

class Menu extends VeggieMenu implements Meat

This is unnecessary complexity, it just give the illusion of structuring and it also looses design information. If we can define both hierarchies we have to note that there is no dependency between Meat and Vegetable so we should use delegation:

class Menu implements Vegetable, Meat {

private final Meat meat;

private final Vegetable vegetable;

//let your IDE create the delegate methods here

}