简体   繁体   English

如何“适当地”重写基类方法?

[英]How to “properly” override a base class method?

Whenever i override a method of a base class, other than my implementation of this method, i seem to have 3 choices. 每当我重写基类的方法时,除了我对该方法的实现以外,我似乎都有3个选择。

1) Call base.Method(), and then provide my implementation. 1)调用base.Method(),然后提供我的实现。

2) Provide my implementation and then call base.Method() 2)提供我的实现,然后调用base.Method()

3) Just provide my implementation. 3)只提供我的实现。

Recently while using a library i have realized few bugs that were introduced because of not implementing the method as expected by the library. 最近,在使用库时,我意识到由于未实现库期望的方法而引入的一些错误。 I am not sure if that is bad on part of library, or something wrong in my understanding. 我不确定这对库的某些方面是否不好,或者我认为是错误的。

I will take one example. 我举一个例子。

public class ViewManager {
     public virtual void Customize(){
        PrepareBaseView();
     }
}

public class PostViewManager {
     public override void Customize(){
        base.Customize();
        PreparePostView();
     }
}


public class PreViewManager {
     public override void Customize(){
        PreparePreView();
        base.Customize();
     }
}


public class CustomViewManager {
     public override void Customize(){
        PrepareCustomView();
     }
}

My question here is that how could a child class know (without taking a look at base class implementation) which order (or option) is being expected by the parent class? 我的问题是,子类如何知道(不看基类的实现)父类期望哪个顺序(或选择)? Is there a way in which parent class could enforce one of the three alternates to all the deriving classes? 有没有一种方法可以使父类对所有派生类强制实施三个替代之一?

how could a child class know (without taking a look at base class implementation) which order (or option) is being expected by the parent class? 子类如何知道(不看基类的实现)父类期望哪个顺序(或选项)?

There is no way to "know" this when you are subclassing and overriding a method. 在子类化和重写方法时,无法“知道”这一点。 Proper documentation is really the only option here. 正确的文档实际上是这里唯一的选择。

Is there a way in which parent class could enforce one of the three alternates to all the deriving classes? 有没有一种方法可以使父类对所有派生类强制实施三个替代之一?

The only option here is to avoid the issue. 这里唯一的选择是避免问题。 Instead of allowing the subclass to override the method, it can be declared non-virtual, and call a virtual method in the appropriate place. 可以允许它声明为非虚拟方法,而不是允许子类覆盖该方法,并在适当的位置调用该方法。 For example, if you want to enforce that subclasses "call your version first", you could do: 例如,如果您要强制子类“先调用您的版本”,则可以执行以下操作:

public class BaseClass {
    public void Method() // Non-virtual
    {
          // Do required work

          // Call virtual method now...
          this.OnMethod();
    }

    protected virtual void OnMethod()
    { // Do nothing
    }
 }

The subclasses can then "override" OnMethod, and provide functionality that happens after "method"'s work. 然后,这些子类可以“覆盖” OnMethod,并提供在“方法”工作之后发生的功能。

The reason this is required is that virtual methods are designed to allow a subclass to completely replace the implementation of the parent class. 之所以需要这样做,是因为虚方法被设计为允许子类完全替代父类的实现。 This is done on purpose. 这是有目的的。 If you want to prevent this, it's better to make the method non-virtual. 如果要防止这种情况,最好将方法设为非虚拟方法。

This is why I feel virtual methods are dangerous when you ship them in a library. 这就是为什么当您将虚拟方法运送到库中时我感到它们很危险的原因。 The truth is you never really know without looking at the base class, sometimes you have to fire up reflektor, read documentation or approach it with trial and error. 事实是,如果不看基类就永远不会真正知道,有时您必须启动反射器,阅读文档或通过反复试验来接近它。

When writing code myself I've always tired to follow the rule that says: 自己编写代码时,我总是很厌倦遵循以下规则:

Derived classes that override the protected virtual method are not required to call the base class implementation. 不需要覆盖覆盖受保护的虚拟方法的派生类来调用基类实现。 The base class must continue to work correctly even if its implementation is not called. 即使未调用其实现,基类也必须继续正常工作。

This is taken from http://msdn.microsoft.com/en-us/library/ms229011.aspx , however this is for Event design though I believe I read this in the Framework Design Guidelines book ( http://www.amazon.com/Framework-Design-Guidelines-Conventions-Libraries/dp/0321246756 ). 这取自http://msdn.microsoft.com/zh-cn/library/ms229011.aspx ,但这是用于事件设计的,尽管我相信我在《框架设计指南》一书( http://www.amazon .com / Framework-Design-Guidelines-Conventions-Libraries / dp / 0321246756 )。

However, this is obviously not true, ASP.NET web forms for example require a base call on Page_Load. 但是,这显然是不正确的,例如,ASP.NET Web表单需要在Page_Load上进行基础调用。

So, long and short, it varies and unfortunately there is no instant way of knowing. 因此,总之,它是多种多样的,不幸的是,没有即时的了解方法。 If I'm in doubt I will omit the call initially. 如果有疑问,我会先省略该呼叫。

The short answer is no. 最简洁的答案是不。 You can't enforce in what order the child calls the base method, or if it calls it at all. 您不能强制孩子以什么顺序调用基本方法,或者根本不能执行。

Technically this information should be included in the base object's documentation. 从技术上讲,此信息应包含在基础对象的文档中。 If you absolutely must have some code run before or after the child class' code than you can do the following: 如果绝对必须在子类的代码之前或之后运行某些代码,则可以执行以下操作:

1) Create a non-virtual function in the base class. 1)在基类中创建一个非虚函数。 Let's call it MyFunction 我们称之为MyFunction

2) Create a protected virtual function in the base class. 2)在基类中创建一个受保护的虚函数。 Let's call it _MyFunction 我们称它为_MyFunction

3) Have deriving classes extend the _MyFunction method. 3)具有派生类扩展了_MyFunction方法。

4) Have MyFunction call _MyFunction and run the code it needs to run before or after calling it. 4)让MyFunction调用_MyFunction并在调用之前或之后运行它需要运行的代码。

This method is ugly and would require a lot of extra code, so I recommend just putting a notice in the documentation. 此方法很丑陋,并且需要大量额外的代码,因此我建议您在文档中添加一个注意事项。

The requirements of the base class should be documented by the library designer. 基类的要求应由库设计者记录。 This issue is the reason why some libraries contain mainly sealed classes. 此问题是某些库主要包含密封类的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM