9

We can do something like this:

// in base class protected virtual void Init(){ //do stuff that all objects need to do } //in derived class protected override void Init(){ base.Init(); // if you forget this but it compiles all hell breaks loose //do derived stuff related to this object } 

I spent a good 15 minutes with a logic error because i simply forgot the base init call.

But there is no keyword to "demand" or contractually force the derived method to call the base equivalent. So if you forget, you're going to have a bad time in some cases where you need to call the base. Or other times where you call base and the derived class didn't need to because it overrides all the base values rather than some of them.

Is there a way to make this more robust/strict so such forgetfulness does not occur.

10
  • 1
    Do you call the base method first? Last? Somewhere in the middle? It’s... not necessarily a bad pattern - base exists in the first place after all - but it is rare. Rare enough that it never warranted the cost of complicating the language and its implementations. Commented Jul 24, 2018 at 2:46
  • 1
    There are cases where you actually want to replace the implementation outright and not call the base method. Same is true of Java, C++, Ruby, Python, etc. They all allow you to either explicitly call the base method, or not. Not to mention, the question of when in the method you are trying to call base (before everything else, after everything else, or somewhere in the middle). Commented Jul 24, 2018 at 2:47
  • 1
    Possible duplicate of Do any OO languages support a mechanism to guarantee an overriden method will call the base? Commented Jul 24, 2018 at 7:51
  • I wonder if an event handler better fits your use case Commented Jul 24, 2018 at 13:26

1 Answer 1

16

Because same effect could already be achieved by a standard pattern of empty overridables.

If all of your non-sealed methods have empty body, it would not matter if they are called from overridden method. Use method template pattern to seal your implementation, and leave only empty methods exposed for override:

public sealed override void callMe() { before(); overrideMe(); after(); } protected virtual void overrideMe() { // left empty to be optionally implemented in children } 

Seal methods with mandatory calls, and implementor won't be able to circumvent those.

18
  • 2
    @DavidArno That problem wasn't freshly introduced by this change. It applied to changes in the base version of Init in the original problem statement just as much. To quote the Wikipedia page you linked to: "The fragile base class problem is a fundamental architectural problem of object-oriented programming systems". Commented Jul 24, 2018 at 7:48
  • 1
    @DavidArno the goal here is to establish a compiler enforced contract of child-parent communication. It is pretty strict and obvious. Please suggest an example of parent class change that would break a child in a non-obvious manner. Commented Jul 24, 2018 at 8:12
  • 2
    I don't think that child breaking parent is better than parent breaking child. And the point about coupling applies to both original (init) and this (empty method) implementations. Commented Jul 24, 2018 at 12:00
  • 1
    @DavidArno: The frailty you're pointing at is irrelevant for OP's case where he wishes to enforce proper usage in derived classes. He's not happy if it just builds, he's happy if the derived class does exactly what its base class stipulates. If you wish to enforce this type of stipulations (which he does), and you've already created derived classes, then you either should no longer touch the base class (at least not its stipulations for derived classes), or accept the fact that you need to revisit your derived classes to ensure that your changed stipulations are still being followed. Commented Jul 24, 2018 at 12:56
  • 2
    @DavidArno: I could claim that any interface is similarly fragile. Any change you make to it is liable to break the classes implementing the interface. On principle, it's the exact same thing. But you need to consider that interfaces are intended specifically because they are a set of enforced rules that need to be followed. A base class which hosts the public methods and forces its derived classes to implement protected override methods inherently puts a joint responsibility on the base class and its derived classes. It's not a flaw if it's an explicit intention. Commented Jul 24, 2018 at 13:02

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.