Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open-closed principle and Java "final" modifier

Tags:

The open-closed principle states that "Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification".

However, Joshua Bloch in his famous book "Effective Java" gives the following advice: "Design and document for inheritance, or else prohibit it", and encourages programmers to use the "final" modifier to prohibit subclassing.

I think these two principles clearly contradict each other (am I wrong?). Which principle do you follow when writing your code, and why? Do you leave your classes open, disallow inheritance on some of them (which ones?), or use the final modifier whenever possible?

like image 280
rmaruszewski Avatar asked Mar 18 '09 12:03

rmaruszewski


People also ask

What is Open Closed Principle in Java?

In object-oriented programming, the open–closed principle states "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification"; that is, such an entity can allow its behaviour to be extended without modifying its source code.

What is the difference between implementing the Open Closed Principle OCP using inheritance and implementing it using polymorphism?

OCP is not different from Inheritance, rather the "Open" part of the OCP is open for extension, but should be closed for modification. I.e. the code should only modified for errors/bugs but for new extension or change to the functionality it should be extended.

What is open close principle with example?

The Open-Close principle (OCP) is the O in the well known SOLID acronym. A module will be said to be open if it is still available for extension. For example, it should be possible to add fields to the data structures it contains, or new elements to the set of functions it performs.

Is inheritance Open Closed Principle?

Unfortunately, Bertrand Mayer proposes to use inheritance to achieve this goal: “A class is closed, since it may be compiled, stored in a library, baselined, and used by client classes. But it is also open, since any new class may use it as parent, adding new features.


2 Answers

Frankly I think the open/closed principle is more an anachronism than not. It sems from the 80s and 90s when OO frameworks were built on the principle that everything must inherit from something else and that everything should be subclassable.

This was most typified in UI frameworks of the era like MFC and Java Swing. In Swing, you have ridiculous inheritance where (iirc) button extends checkbox (or the other way around) giving one of them behaviour that isn't used (I think it's its the setDisabled() call on checkbox). Why do they share an ancestry? No reason other than, well, they had some methods in common.

These days composition is favoured over inheritance. Whereas Java allowed inheritance by default, .Net took the (more modern) approach of disallowing it by default, which I think is more correct (and more consistent with Josh Bloch's principles).

DI/IoC have also further made the case for composition.

Josh Bloch also points out that inheritance breaks encapsulation and gives some good examples of why. It's also been demonstrated that changing the behaviour of Java collections is more consistent if done by delegation rather than extending the classes.

Personally I largely view inheritance as little more than an implemntation detail these days.

like image 141
cletus Avatar answered Oct 19 '22 14:10

cletus


I don't think the two statements contradict each other. A type can be open for extension and still be closed for inheritance.

One way to do this is to employ dependency injection. Instead of creating instances of its own helper types, a type can have these supplied upon creation. This allows you to change the parts (i.e. open for extension) of the type without changing the type itself (i.e. close for modification).

like image 43
Brian Rasmussen Avatar answered Oct 19 '22 12:10

Brian Rasmussen