私有助手方法的继承和重写

本文关键字:继承 重写 方法 | 更新日期: 2023-09-27 17:57:33

我发现了几个问题,解释了用于覆盖和隐藏方法的virtual/override/new关键字,但它们似乎无法解决我遇到的情况。我有在MVC控制器中进行验证的代码,如下所示:

public class AController : BaseController
{
    private bool validate()
    {
        //code for A validation
        return base.validate();
    }
}
public class BController : BaseController
{
    private bool validate()
    {
        //code for B validation
        return base.validate();
    }
}
public class BaseController : Controller
{
    protected bool validate()
    {
        //code for common validation
        return isValid;
    }
}

A和B都在创建和编辑POST方法中调用this.validate()。据我所知,这很好,但我不知道何时/是否应该使用虚拟/覆盖。受保护的基本方法应该是虚拟的吗?如果是的话,它会改变什么吗?当我不使用"覆盖"时,我不会收到编译器关于"隐藏继承成员"的警告。我猜虚拟/覆盖不会起作用,因为validate()是一个私有方法。我知道我也可以将BaseController.validate()重命名为其他东西,比如BaseValidate(),而不必考虑重写。这有关系吗?或者该方法被称为"Validate"还是不同的名称是一样的吗?

私有助手方法的继承和重写

使用您的代码,如果BaseController中的某个方法想要验证控制器,它就无法验证。它可以调用validate,但由于它是一个非虚拟方法,它将只执行基类的有效性定义。您可能希望它使用实际派生类型的有效性定义,而不是省略额外的检查。

正如您所猜测的,由于方法是private,因此不会出现由于遮蔽成员而导致的编译器警告。private方法不可能覆盖该方法;它们永远不可能是虚拟的。它必须始终覆盖同一方法的任何继承定义。

我应该使用virtual/override吗?

我假设派生控制器中的其他方法调用validate()。在这种情况下,它看起来不像你需要它。

如果您想以另一种方式构建验证逻辑,基类调用子类中可选的附加验证器,那么您可能会从重写中受益。

public class AController : BaseController
{
    protected override bool additionalValidate()
    {
        //code for A validation
        return isValid;
    }
}
public class BController : BaseController
{
    protected override bool additionalValidate()
    {
        //code for B validation
        return isValid;
    }
}
public class BaseController : Controller
{
    virtual bool additionalValidate() {
        return true;
    }
    protected bool validate()
    {
        //code for common validation
        return isValid && additionalValidate();
    }
}

此模式称为模板方法。它不像您的实现那样脆弱,因为子类不能"忘记"调用基类验证。

当我不使用"覆盖"时,我不会收到编译器关于"隐藏继承成员"的警告。

您是正确的,这是因为子类中的bool validate()方法是private

您可以使BaseController抽象化。

然后创建一个所有派生类型都必须实现的抽象属性。

所以,你的例子会变成:

public class AController : BaseController
{
    protected override bool abstractValidation()
    {
       //code for A validation
    }
}
public class BController : BaseController
{
    protected override bool abstractValidation()
    {
       //code for B validation
    }
}
public abstract class BaseController
{
    protected abstract bool abstractValidation();
    protected bool validate()
    {
        //code for common validation
        //then, call the implementations validation method
        var isValid = abstractValidation();
        return isValid;
    }
}