Метод должен быть переопределен, но не является абстрактным?

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

Что я ищу? Я ищу правильную вещь?

4 ответов


Если у базового класса есть что сказать, но вы хотите, чтобы он переопределялся "каждый раз", тогда у меня будет пара методов:

public void DoSomething() {
    //things to do before
    DoSomethingCore();
    //things to do after
}
protected abstract void DoSomethingCore();

если ваш базовый класс что-то в методе, но вы хотите убедиться, что каждый подкласс вынужден реализовать некоторую часть метода, тогда вы хотите шаблон метода шаблона, как описано в ответе Марка Гравелла.

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

public abstract class FooBase {
    public abstract void DoStuff();
}

public sealed class FooImpl : FooBase {
    public override void DoStuff {
        //default widget-munging code
    }
}

теперь любые классы, наследующие от FooBase, должны реализовать DoStuff (), но у вас есть реализация по умолчанию FooImpl, от которой подклассы не могут наследовать.

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

public sealed class Foo {
    private IFooStrategy _strategy;
    public Foo(IStrategy strategy) {
        _strategy = strategy;
    }
    void DoStuff() {
        _strategy.DoStuff();
    }
    public static IFooStrategy DefaultStrategy {
        //return singleton instance of the default strategy
    }
}

теперь вместо подклассов Foo вы вместо этого создаете новые реализации интерфейса IFooStrategy и передаете их своему экземпляру Foo. Так что вы могли бы сделать:

new Foo(Foo.DefaultStrategy);

или

new Foo(new DifferentStrategy());

мы ищем virtual способ (использовать этот модификатор, чтобы разрешить переопределение метода), но вы не можете заставить пользователя заменить его. Принуждение к этому не имело бы смысла, если у вас есть тело, так как можно просто назвать базу.YourMethod () и ничего не делать, что делает то же самое, что и не переопределение метода в первую очередь.

public virtual YourMethod() {
   // your base class code here
}

а затем переопределяющий метод в другом классе:

public override YourMethod() {
   // code to do before the base call
   base.YourMethod();
   // code to do after the base call
}

похоже, что ваша базовая реализация никогда не будет вызвана. Почему вы хотите предоставить реализацию, до которой никто не может добраться (прыжки через обручи не выдерживают)