Java – Inheritance vs additional property with null value

classinheritancejavanull

For classes with optional fields, is it better to use inheritance or a nullable property? Consider this example:

class Book {
    private String name;
}
class BookWithColor extends Book {
    private String color;
}

or

class Book {
    private String name;
    private String color; 
    //when this is null then it is "Book" otherwise "BookWithColor"
}

or

class Book {
    private String name;
    private Optional<String> color;
    //when isPresent() is false it is "Book" otherwise "BookWithColor"
}

The code depending on these 3 options would be:

if (book instanceof BookWithColor) { ((BookWithColor)book).getColor(); }

or

if (book.getColor() != null) { book.getColor(); }

or

if (book.getColor().isPresent()) { book.getColor(); }

The first approach looks more natural to me, but maybe it is less readable because of the necessity to do casting. Is there some other way to achieve this behavior?

Best Answer

It depends on the circumstances. The specific example is unrealistic since you wouldn't have a subclass called BookWithColor in a real program.

But in general, a property which only makes sense for certain subclasses should only exist in those subclasses.

For example if Book has PhysicalBook and DigialBook as descendents, then PhysicalBook might have a weight property, and DigitalBook a sizeInKb property. But DigitalBook will not have weight and vice versa. Book will have neither property, since a class should only have properties shared by all descendents.

A better example is looking at classes from real software. The JSlider component has the field majorTickSpacing. Since only a slider has "ticks", this field only makes sense for JSlider and its descendants. It would be very confusing if other sibling components like JButton had a majorTickSpacing field.