Как обеспечить вызов метода (в базовом классе) при вызове переопределенного метода? - PullRequest
7 голосов
/ 17 июля 2009

У меня есть такая ситуация, когда при вызове метода AbstractMethod из ImplementClass я хочу применить метод MustBeCalled в AbstractClass вызывается. Я никогда не сталкивался с такой ситуацией раньше. Спасибо!

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

Ответы [ 4 ]

8 голосов
/ 17 июля 2009

Можно было бы сделать так, чтобы класс Abstract выполнял вызов таким образом. В противном случае в 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?
    }
}

Выполнение этого создает желаемый публичный метод в абстрактном классе, предоставляя абстрактному классу информацию о том, как и в каком порядке вызываться объекты, и в то же время позволяя конкретному классу обеспечивать необходимую функциональность.

6 голосов
/ 17 июля 2009

Как насчет

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?
    }
}
0 голосов
/ 17 июля 2009

Одна вещь, которую предыдущие решения игнорируют, заключается в том, что 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!

Единственный способ преодолеть это - использовать делегирование, а не наследование, поскольку классы можно определить как закрытые. И я использую пространство имен и «внутренний» модификатор доступа, чтобы предотвратить предоставление новой реализации для реализации классов. Кроме того, метод для переопределения должен быть определен как защищенный, иначе пользователи могут вызывать его напрямую.

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");
    }
}
0 голосов
/ 17 июля 2009

Почему нельзя просто вызвать метод в AbstractMethod () класса Implement?

...