开发者

Can I have a default method in a base class that's always called before child implementations?

C# here - is it possible to have an abstract base class define a method with default behavior, and have this default be called before a child class implementation? For example:

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));   // 开发者_C百科prints 0

Basically I don't want to have to put the same boilerplate in every child implementation...


Callable by who would be the question. The way that I've dealt with this issue in the past is to create 2 methods, a public one in the base class and a protected abstract one (perhaps virtual with no implementation) as well.

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


If you want to make sure that the class method is always called, look at the Template method pattern Also, your question is not new, check this one


IF i am understading you right Take a look at might be helpful Template Method pattern


I don't think it's possible to force a base implementation to run without the explicit base.GetX(...) call.

I usually end up wrapping something like that in the base class. So in your case something like this:

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


Template method pattern is the way to go. Judging by your requirement, you'd want your base class function to always execute a method. So you can define a template in your base class such as

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

Keep in mind that it may not be the best solution: http://tech.puredanger.com/2007/07/03/pattern-hate-template/


What you describe would be a good usage case for a "private virtual" function if such a thing were permitted; the semantics would be that derived classes could override the function, but the base version would only be callable from the override, and the override would only be callable from some other function in the base.

There is a way to enforce this, but it's a bit ugly. If the goal is for X.ChainedMethod() to be callable only from within X.WrapperMethod(), create a dummy public class Y within X that has an internal constructor, and a private dummy class Z which inherits from Y and has a public parameterless constructor. Then have declare X.ChainedMethod<T>() where T:Z, new(). The only possible class which would fill those constraints would be Y, and nothing outside X can access Y.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜