I am not working yet, just studying and recently dealing with SOLID principles. I have read quite a lot about open closed principle but unfortunately most of the books and articles share the same examples. I do not understand the following: if the class should not be changed after it has been
But it does not address the issue if the base class implementation needs to change (for example a method that is implemented at the base class level). Why this principle does not address that?
The point of keeping it open to extension is to avoid needing to make that direct modification.
Directly modifying is always possible but can come with significant costs. The OCP asks you to start with a design that hopefully avoids the need for direct modification, and it's costs, as requirements change.
A design that allows some polymorphic replacement of the offending behavior means you don't have to touch the code you wish to change. You just write new code.
That means if you find you HAVE to change the base class implementation you've already failed to follow OCP. You should have used a design that would have allowed that implementation to be replaced with other code written somewhere else.
There are many ways to do this. Polymorphism comes in many forms. Inheritance, composition and delegation, wrappers, it goes on and on. Any of these can avoid seeing that base code implementation called.
If you write code that directly accesses this implementation in a way that gives no one any way to replace it with some other implementation then you violated OCP before the change. Don't do that unless you're either very sure that the implementation will never need to change or that you're willing to take on the costs of making direct modifications in the implementaion.
It's not that the principle doesn't address a need to directly change base class implementation. It expressly tells you to avoid creating a need to do that.
In the real world sometimes changing requirements means changing modifying things, but there are ways to mitigate how often that happens. SOLID is a list of principles that sometimes compete with each other and its up to the developer to determine which are the most important for the situation at hand.
For changing algorithms a common solution is to use the strategy pattern to require the algorithm to be provided when the object is created at run time and therefore different objects can be used. This also is part of the dependency inversion principle. Lets use calculating grades as an example, there can be multiple ways to curve or not curve grades, so your class that calculates grades requires a function to provide that curve as part of its creation. This means you can have the same class calculate grades differently without modifying that class.
Another way to help keep classes closed is involved with the single responsibility principle, which also can help decide when a class need to be modified. If there is a change to the responsibility of a class it's very likely that you will need to modify it. if a class has multiple responsibilities its far more likely to need to be modified and have a greater chance of causing bugs because you are modifying multiple responsibilities at once. For calculating grades you can have a base class that only cares about the process of calculating the score, and extend with classes responsible for formatting that score as a letter, percentage, pass/fail, or something else.
Ideally the only reason a class should get modified is the requirements directly related to its responsibility change. Depending on the domain this may be constant or extremely rare.
A class is only supposed to be closed to modification. It's open to extension though.
So if your class has a method,
AddOne, that adds one to a value, then
AddOne should not one day be changed to add two to a value. That would be modification and the class is closed to that.
Instead, a new method,
AddTwo is added, that handles that new algorithm. That's extension and the class is open to that.
The exception to the rule being if a bug is found in
AddOne. Then its behaviour can be modified.