Virtual Method Design

I wonder under what circumstances would you choose the first or second design:

First project: the child method must call the base method

public abstract class Base { public virtual void Enable() { IsEnable = true; } public virtual void Disable() { IsEnable = false; } public bool IsEnable { get; private set; } } public class Child : Base { public override void Enable() { /* do stuffs */ base.Enable(); } public override void Disable() { /* do stuffs */ base.Disable(); } } 

Second construction: a virtual method is used to make sure that the child does not forget to call the base

 public abstract class Base { public void Enable() { IsEnable = true; OnEnable(); } public void Disable() { IsEnable = false; OnDisable(); } public bool IsEnable { get; private set; } public virtual void OnEnable() {} public virtual void OnDisable() {} } public class Child : Base { override void OnEnable() { /* do stuffs */ } override void OnDisable() { /* do stuffs */ } } 

thanks

+4
source share
4 answers

It depends on whether you really want to install IsEnable or not. If you can imagine scenarios in which the user does not want to install it, I suppose you leave them to them to call the base method. Otherwise, do it for them.

+3
source

The second, template approach , in my opinion, is better. This allows you to ensure that some basic functionality is always invoked, and gives you the opportunity to add some if none of them are present at first without the risk of breaking into any subclass.

+3
source

Once you create a virtual method, you give the derived class a chance to break your class. The responsible developer always asks himself: "Should I name the base implementation?" Guidance for this should always come from the documentation. MSDN uses the standard wording:

Notes for Inheritors:

When overriding Xxxxx in a derived class, be sure to call the base class of Xxxx, so blablah happens.

C # language makes this easy with the keyword "base". Based on the assumption that this documentation is unavailable or unclear, your second example strongly prevents you from calling another method of the base class. In the end, he / she will not use the standard template. Use this template only if you want the inheritor not to call the base class method.

+2
source

In the first case, when the overring class can prevent the setting of Enable, I believe that Enable and Disable can potentially be misleading method names.

Something like TryEnable and TryDisable is likely to be more accurate, implying that there are situations where you cannot enable it.

The third possible situation could be served if you took Example 2 and changed it so that the base class would call OnEnable before setting the flag:

 public void Enable() { OnEnable(); // Exceptions raised from here prevent the flag being set. IsEnable = true; } 

Then overriding classes can prevent the flag from being set by throwing an exception if an error occurs. Thus, error situations can prevent the flag from being changed.

Just food for thought.

+1
source

Source: https://habr.com/ru/post/1299213/


All Articles