How to enforce a method call (in the base class) when overriding method is invoked?

被刻印的时光 ゝ 提交于 2019-12-19 17:34:22

问题


I have this situation that when AbstractMethod method is invoked from ImplementClass I want to enforce that MustBeCalled method in the AbstractClass is invoked. I’ve never come across this situation before. Thank you!

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

回答1:


An option would be to have the Abstract class do the calling in this manner. Otherwise, there is no way in c# to require an inherited class to implement a method in a certain way.

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

Doing this creates the desired public facing method in the abstract class, giving the abstract class over how and in what order things are called, while still allowing the concrete class to provide needed functionality.




回答2:


How about

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



回答3:


One thing the preceding solutions ignore is that ImplementClass can redefine MethodToBeCalled and not call 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();
    }
}

If only C# allowed non-overridden methods to be sealed - like Java's final keyword!

The only way I can think of to overcome this is to use delegation rather than inheritance, because classes can be defined as sealed. And I'm using a namespace and the "internal" access modifier to prevent providing a new implementation on implementing classes. Also, the method to override must be defined as protected, otherwise users could call it directly.

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");
    }
}



回答4:


Why can't you just call the method in the AbstractMethod() of Implement class?



来源:https://stackoverflow.com/questions/1141104/how-to-enforce-a-method-call-in-the-base-class-when-overriding-method-is-invok

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!