Переопределение вложенных функций класса или использование делегатов? ** - PullRequest
3 голосов
/ 25 апреля 2011

У меня есть base class, который имеет вложенный тип внутри.Есть функция во внешнем (базовом) типе, которая позже будет переопределена его потомками.На самом деле эта функция принадлежит inner type с точки зрения OO, но она мне все еще нужна, чтобы быть переопределенной на subtypes из base class.

Должен ли я использовать эту функцию как callback из inner type или просто переместите его внутрь inner type и давайте subtypes переопределить его оттуда?

РЕДАКТИРОВАТЬ: Пример кода добавлен

class A
{
    protected void func() { /* do something */ }
    class B { /**/ }
}

// OR

class A
{
    class B
    {
        protected void func() { /* do something */ }
    }
}

// Then

class C : A
{
    override func() { /**/ }
}

Ответы [ 4 ]

2 голосов
/ 25 апреля 2011

Я предлагаю создать делегат для функции внутреннего типа , которая инициируется конструктором базового класса :

internal class BaseClass
{
    public BaseClass(Action myAction)
    {
        this.innerType = new InnerType(myAction);
    }

    public BaseClass()
    {
        // When no function delegate is supplied, InnerType should default to
        // using its own implementation of the specific function
        this.innerType = new InnerType();
    }
}

Как видите, производные типы могут вызывать базовый конструктор с :base (overridenAction), где они могут обеспечить собственную реализацию функции вплоть до самого внутреннего типа. Конечно, вы не обязаны использовать Action, но любой делегат, которого вы хотите.

1 голос
/ 25 апреля 2011

Так внешний класс может служить стратегией для внутреннего класса обслуживания.

Обратите внимание, что использование имен шаблонов, таких как TemplateMethod и Strategy, в качестве реальных имен классов не рекомендуется, используйте любоеимеет смысл в области.То же самое относится к Outer и Inner.

public class Consumer
{
    public void Foo()
    {
        IOuterFoo fooService = new Derived();
        fooService.OuterFoo();
    }
}

// ...

public interface IOuterFoo
{
    void OuterFoo();
}

abstract class Base : Base.IStrategy, IOuterFoo
{
    public void OuterFoo() { _service.Foo(); }

    private readonly InnerService _service;

    protected Base() { _service = new InnerService(this); }

    private interface IStrategy { void Foo(); }

    private class InnerService
    {
        private readonly IStrategy _strategy;
        public InnerService(IStrategy strategy) { _strategy = strategy; }
        public void Foo() { _strategy.Foo(); }
    }

    void IStrategy.Foo() { TemplateMethodFoo(); }

    protected abstract void TemplateMethodFoo();
}

class Derived : Base
{
    protected override void TemplateMethodFoo()
    {
        throw new NotImplementedException();
    }
}
1 голос
/ 25 апреля 2011

В этом сценарии:

class A
{
    class B
    {
        protected void func() { // do something }
    }
}

Вы не можете наследовать от класса A и переопределить func() в классе B.

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

class A
{
    private B _MyB;
    public A(ISomeBehaviour behaviour)
    {
        _MyB = new B(behaviour);
    }
}

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

1 голос
/ 25 апреля 2011

ИМО, что вы описываете, выглядит как Шаблон разработки стратегии .Подумайте об использовании этого шаблона.Ваш код будет гораздо более удобен в обслуживании, так как содержит хорошо узнаваемый шаблон.Вы также можете взглянуть на шаблон проектирования состояния , обычно вам приходится выбирать между этими двумя, они тесно связаны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...