Suppose I have the following contrived code:
abstract class Root { public abstract void PrintHierarchy(); } class Level1 : Root { override public void PrintHierarchy() { Console.WriteLine("Level1 is a child of Root"); } } class Level2 : Level1 { override public void PrintHierarchy() { Console.WriteLine("Level2 is a child of Level1"); base.PrintHierarchy(); } }
If I consider only the Level2 class, I immediately see that Level2.PrintHierarchy follows the open / closed principle , because it does something by itself, and it calls the base method, which it overrides.
However, if I consider only the Level1 class, it seems to violate OCP because it does not call base.PrintHierarchy - in fact, in C # the compiler forbids it with the error "Can't call" abstract base element ".
The only way to make Level1 seem to follow OCP is to change Root.PrintHierarchy to an empty virtual method, but then I can no longer rely on the compiler to force classes to implement PrintHierarchy .
The real problem I'm having while saving the code here is to see dozens of override methods that don't call base.Whatever() . If base.Whatever is abstract, then accurate, but if not, then the Whatever method may be a candidate that should be pulled into the interface, and not a specific method that can override, or the class or method needs to be reorganized into some other mode, but in any case, it clearly indicates a poor design.
Except that Root.PrintHierarchy is abstract or puts a comment inside Level1.PrintHierarchy , do I have any other options to quickly determine if a class like Level1 breaking OCP?
There was a lot of good discussion in the comments as well as good answers. I am having trouble figuring out exactly what you can ask. I think I'm upset by what @Jon Hanna points out , sometimes the virtual method simply indicates: “You have to implement me”, while in other cases it means “you have to forgive me - if you do not call the basic version, you will break my project!" But C # does not offer any way to indicate which one you have in mind, other than this abstract or interface, it is obviously a “mandatory implementation” of the situation. (Is it something in the Codes of Contracts, which, in my opinion, is a little beyond)
But if a binding language was installed in any language vs. a must-extend decorator, this would probably create huge problems for unit testing if it couldn’t be disabled. Are there any such languages? It sounds more like a design under a contract , so I wouldn’t be surprised if he were in Eiffel, for example.
The end result is probably, as @ JordĂŁo says , and it is completely contextual; but I'm going to leave the discussion open for a while before accepting any answers.