【问题标题】:Can I have a default method in a base class that's always called before child implementations?我可以在子实现之前始终调用基类中的默认方法吗?
【发布时间】:2011-03-17 19:44:28
【问题描述】:

这里的 C# - 是否可以让抽象基类定义具有默认行为的方法,并在子类实现之前调用此默认值?例如:

public abstract class Base
{
    public virtual int GetX(int arg)
    {
        if (arg < 0) return 0;
        // do something here like "child.GetX(arg)"
    }
}

public class MyClass : Base
{
    public override int GetX(int arg)
    {
        return arg * 2;
    }
}

MyClass x = new MyClass();
Console.WriteLine(x.GetX(5));    // prints 10
Console.WriteLine(x.GetX(-3));   // prints 0

基本上我不想在每个子实现中都放置相同的样板...

【问题讨论】:

  • 从某种意义上说有点违背override 的观点,但我理解避免样板的愿望。也许,您可以通过始终在子覆盖开始时调用基类的方法来使样板文件更简单。不过,除了惯例,我不知道有什么方法可以强制执行。

标签: c# oop


【解决方案1】:

可以由谁提出问题。我过去处理这个问题的方法是创建 2 个方法,一个在基类中的公共方法和一个受保护的抽象方法(可能是没有实现的虚拟方法)。

public abstract class Base
{
  public int GetX(int arg)
  {
    // do boilerplate

    // call protected implementation
    var retVal = GetXImpl(arg);

    // perhaps to more boilerplate
  }

  protected abstract int GetXImpl(int arg);
}

public class MyClass : Base
{
  protected override int GetXImpl(int arg)
  {
    // do stuff
  }
}

【讨论】:

    【解决方案2】:

    如果要确保始终调用类方法,请查看Template method pattern 另外,您的问题并不新鲜,请查看this one

    【讨论】:

      【解决方案3】:

      如果我理解你的话,看看可能会有所帮助 Template Method pattern

      【讨论】:

        【解决方案4】:

        我认为如果没有明确的base.GetX(...) 调用,就无法强制基本实现运行。

        我通常最终在基类中包装类似的东西。所以在你的情况下是这样的:

        public abstract class Base
        {
            public override int GetX(int arg)
            {
                if(arg < 0) return 0;
        
                return OnGetX(arg);
            }
        
            protected abstract OnGetX(int arg);
        }
        
        public class MyClass : Base
        {
            protected override int OnGetX(int arg)
            {
                return arg * 2;
            }
        }
        
        MyClass x = new MyClass();
        Console.WriteLine(x.GetX(5));    // prints 10
        Console.WriteLine(x.GetX(-3));   // prints 0
        

        【讨论】:

          【解决方案5】:

          模板方法模式是要走的路。根据您的要求,您希望基类函数始终执行一个方法。所以你可以在你的基类中定义一个模板,比如

          public void ExecuteSteps()
          {
            Step1(); //Defined in base, can't be overridden.
            Step2(); //Defined as virtual in base, so sub-classes can override it
          } 
          

          请记住,这可能不是最佳解决方案:http://tech.puredanger.com/2007/07/03/pattern-hate-template/

          【讨论】:

            【解决方案6】:

            如果允许这样的事情,您所描述的将是“私有虚拟”功能的一个很好的用例;语义是派生类可以覆盖该函数,但基版本只能从覆盖中调用,而覆盖只能从基中的某个其他函数中调用。

            有一种方法可以强制执行此操作,但它有点难看。如果目标是让X.ChainedMethod() 只能从X.WrapperMethod() 内部调用,则在X 中创建一个虚拟公共类Y,它有一个internal 构造函数和一个私有虚拟类Z,它继承自Y 并具有公共无参数构造函数。然后声明X.ChainedMethod&lt;T&gt;() where T:Z, new()。唯一可能满足这些约束的类是YX 之外的任何东西都不能访问Y

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-11-10
              • 2016-04-08
              • 1970-01-01
              • 2019-08-04
              相关资源
              最近更新 更多