我可以在子类实现之前始终调用的基类中使用默认方法吗?

时间:2011-03-17 19:44:29

标签: c# oop

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

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

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

6 个答案:

答案 0 :(得分:6)

可以问谁是谁。我过去处理这个问题的方法是创建两个方法,一个是基类中的公共方法,另一个是受保护的抽象方法(也许是虚拟的,没有实现)。

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
  }
}

答案 1 :(得分:2)

如果您想确保始终调用类方法,请查看Template method pattern 此外,您的问题不是新问题,请查看this one

答案 2 :(得分:0)

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

答案 3 :(得分:0)

我认为在没有显式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

答案 4 :(得分:0)

模板方法模式是要走的路。根据您的要求判断,您希望基类函数始终执行方法。因此,您可以在基类中定义模板,例如

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/

答案 5 :(得分:0)

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

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