【问题标题】:How to enforce a method call (in the base class) when overriding method is invoked?调用覆盖方法时如何强制方法调用(在基类中)?
【发布时间】:2009-07-17 01:37:58
【问题描述】:

我有这种情况,当从 ImplementClass 调用 AbstractMethod 方法时,我想在 AbstractClassMustBeCalled 方法/strong> 被调用。我以前从未遇到过这种情况。谢谢!

public abstract class AbstractClass
{
    public abstract void AbstractMethod();

    public void MustBeCalled()
    {
        //this must be called when AbstractMethod is invoked
    }
}

public class ImplementClass : AbstractClass
{
    public override void AbstractMethod()
    {
        //when called, base.MustBeCalled() must be called.
        //how can i enforce this?
    }
}

【问题讨论】:

  • 当子类调用 AbstractClass.AbstractMethod 时会引发一个事件来调用 AbstractClass.MustBeCalled。但还是不知道该怎么做。

标签: c# inheritance overriding method-call


【解决方案1】:

一种选择是让抽象类以这种方式进行调用。否则,c#中没有办法要求继承的类以某种方式实现方法。

public abstract class AbstractClass
{
    public void PerformThisFunction()
    {
        MustBeCalled();
        AbstractMethod();
    }

    public void MustBeCalled()
    {
        //this must be called when AbstractMethod is invoked
    }

    //could also be public if desired
    protected abstract void AbstractMethod();
}

public class ImplementClass : AbstractClass
{
    protected override void AbstractMethod()
    {
        //when called, base.MustBeCalled() must be called.
        //how can i enforce this?
    }
}

这样做会在抽象类中创建所需的面向公众的方法,让抽象类知道如何以及以什么顺序调用事物,同时仍然允许具体类提供所需的功能。

【讨论】:

  • 我也使用过这种模式。我相信这实际上是四人组设计模式之一,但我没有我的书来证实这一点。
  • Base.AbstractMethod() 被调用时引发事件怎么样?
  • 我认为它被称为“模板模式”。另外,我认为西蒙的解决方案是一种更好的方法。上述代码中,调用代码可以不经过PerformFunction方法直接调用AbstractMethod。
【解决方案2】:

怎么样

public abstract class AbstractClass
{
    public void AbstractMethod()
    {
        MustBeCalled();
        InternalAbstractMethod();
    }

    protected abstract void InternalAbstractMethod();

    public void MustBeCalled()
    {
        //this must be called when AbstractMethod is invoked
    }
}

public class ImplementClass : AbstractClass
{
    protected override void InternalAbstractMethod()
    {
        //when called, base.MustBeCalled() must be called.
        //how can i enforce this?
    }
}

【讨论】:

  • 在这个实现中,我认为你没有强迫用户调用 MustBeCalled。调用 AbstractClass.AbstractMethod 时,会调用 ImplementClass.AbstractMethod,但不会调用 MustBeCalled。我相信 yshuditelu 有更好的解决方案
【解决方案3】:

前面的解决方案忽略的一件事是,ImplementClass 可以重新定义 MethodToBeCalled 而不会调用 MustBeCalled -

public abstract class AbstractClass
{
    public abstract void AbstractMethod();

    private void MustBeCalled()
    {
        //will be invoked by  MethodToBeCalled();
        Console.WriteLine("AbstractClass.MustBeCalled");
    }

    public void MethodToBeCalled()
    {
        MustBeCalled();
        AbstractMethod();
    }
}

public class ImplementClass : AbstractClass
{
    public override void AbstractMethod()
    {
        Console.WriteLine("ImplementClass.InternalAbstractMethod");
    }

    public new void MethodToBeCalled() {
        AbstractMethod();
    }
}

如果只有 C# 允许密封未覆盖的方法 - 就像 Java 的 final 关键字一样!

我能想到的解决这个问题的唯一方法是使用委托而不是继承,因为类可以定义为密封的。而且我正在使用命名空间和“内部”访问修饰符来防止在实现类上提供新的实现。另外,要覆盖的方法必须定义为protected,否则用户可以直接调用。

namespace Something
{

    public sealed class OuterClass
    {
        private AbstractInnerClass inner;

        public OuterClass(AbstractInnerClass inner)
        {
            this.inner = inner;
        }

        public void MethodToBeCalled()
        {
            MustBeCalled();
            inner.CalledByOuter();
        }

        public void MustBeCalled()
        {
            //this must be called when AbstractMethod is invoked
            System.Console.WriteLine("OuterClass.MustBeCalled");
        }
    }

    public abstract class AbstractInnerClass
    {
        internal void CalledByOuter()
        {
            AbstractMethod();
        }

        protected abstract void AbstractMethod();
    }
}

public class ImplementInnerClass : Something.AbstractInnerClass
{
    protected override void AbstractMethod()
    {
        //when called, base.MustBeCalled() must be called.
        //how can i enforce this?
        System.Console.WriteLine("ImplementInnerClass.AbstractMethod");
    }

    public new void CalledByOuter()
    {
        System.Console.WriteLine("doesn't work");
    }
}

【讨论】:

  • 派生类可能会影响 MethodToBeCalled 这一事实不会对使用派生类对象作为基类对象的代码造成问题。我确实认为,如果允许“私有可覆盖”方法,则可以改进方法层次结构;我不知道是否有任何技术原因他们不能。只能从基类或派生类对同一方法的覆盖中调用私有可重写方法。因此,除了从对最派生版本的基类调用中调用基本实现中的代码之外,将不可能调用代码。
【解决方案4】:

为什么不能直接调用Implement类的AbstractMethod()中的方法?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 2013-03-03
    • 2011-12-13
    • 2011-04-28
    • 2011-11-03
    • 2018-10-15
    相关资源
    最近更新 更多