сигнатура абстрактного метода, наследование и соглашение об именовании "Do" - PullRequest
5 голосов
/ 19 марта 2010

Я изучаю шаблоны проектирования и в примерах кода я видел соглашение, в котором абстрактный класс объявляет метод, например:

public abstract class ServiceBase {
... 

public virtual object GetSomething();

, а затем

protected abstract object DoGetSomething();

Мой вопрос заключается в том, почему существуют эти два метода, поскольку они, похоже, служат одной и той же цели. Это так, что логику метода базового класса GetSomething () нельзя переопределить унаследованными классами? Но опять же, метод помечается как виртуальный, поэтому его можно переопределить в любом случае. В чём здесь польза от реализаторов производных классов для реализации абстрактного метода, когда виртуальный метод может быть вызван в любом случае?

Ответы [ 2 ]

4 голосов
/ 19 марта 2010

Одной из распространенных причин является использование стандартной обработки вокруг абстрактного метода. Например, возможно, абстрактный метод может быть вызван только при определенных обстоятельствах - скажем, после того, как сплайны были повторены. В этом случае имеет смысл проверять _areSplinesReticulated в одном месте - публичном методе GetSomething - вместо того, чтобы требовать от каждой реализации абстрактного метода выполнения своей собственной проверки. Или, может быть, GetSomething на 90% стандартен, но требует немного дополнительной логики или важной информации, которую могут предоставить только производные классы.

Это форма шаблона Template pattern.

Не виртуальный GetSomething означает, что каждый производный класс получает стандартную обработку и получает возможность участвовать только через свою пользовательскую версию DoGetSomething. Если GetSomething является виртуальным, это означает, что производные классы могут обходить стандартную обработку, если они этого хотят. Любая из этих стратегий является жизнеспособной в зависимости от того, является ли стандартная обработка GetSomething неотъемлемой частью логики класса (например, инварианты), или же базовый класс хочет предоставить максимальную гибкость производным классам.

0 голосов
/ 19 марта 2010

Я не видел описанную вами версию, где "GetSomething ()" является виртуальной, но я видел (и писал) классы, подобные этой:

public abstract class Foo
{
    protected abstract void DoBar();

    public void Bar()
    {
        // do stuff that has to happen regardless of how 
        // DoBar() has been implemented in the derived
        // class
        DoBar();
        // do other stuff
    }
}

Поскольку «Bar» не является виртуальным (и я полагаю, вы могли бы также запечатать его, чтобы убедиться), у вас есть возможность «внедрить» код до и после вызова метода «DoBar». Это очень удобно.

...