2010-01-23 3 views
4

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

Первый дизайн: метод ребенок должен назвать базовый метод

public abstract class Base 
{ 
    public virtual void Enable() { IsEnable = true; } 
    public virtual void Disable() { IsEnable = false; } 
    public bool IsEnable { get; private set; } 
} 

public class Child : Base 
{ 
    public override void Enable() { /* do stuffs */ base.Enable(); } 
    public override void Disable() { /* do stuffs */ base.Disable(); } 
} 

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

public abstract class Base 
{ 
    public void Enable() 
    { 
     IsEnable = true; 
     OnEnable(); 
    } 

    public void Disable() 
    { 
     IsEnable = false; 
     OnDisable(); 
    } 

    public bool IsEnable { get; private set; } 
    public virtual void OnEnable() {} 
    public virtual void OnDisable() {} 
} 

public class Child : Base 
{ 
    override void OnEnable() { /* do stuffs */ } 
    override void OnDisable() { /* do stuffs */ } 
} 

Благодарности

+2

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

+0

Во-вторых, если OnEnable/Disable имеет защиту beek, а не public. –

ответ

3

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

3

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

1

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

Что-то вроде TryEnable и TryDisable, вероятно, будет более точным, подразумевая, что есть ситуации, когда вы не можете включить.

Третья возможная ситуация может быть обслужен, если вы взяли пример 2 и изменил это так базовый класс вызывает OnEnable перед установкой флага:

public void Enable() 
{ 
    OnEnable(); // Exceptions raised from here prevent the flag being set. 
    IsEnable = true; 
} 

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

Просто пища для размышления.

2

Как только вы создадите метод виртуальный, вы даете производному классу шанс сломать ваш класс. Ответственный разработчик всегда спрашивает себя: «Должен ли я назвать базовую реализацию?» Руководство для этого всегда должно поступать из документации. MSDN использует стандартные словоблудие:

Примечания для наследующих:

При переопределении ххххх в производном классе , обязательно вызовите метод XXXX базовый класс , так что blablah происходит.

Язык C# упрощает использование ключевого слова «base». Исходя из предположения, что эта документация недоступна или неясна, ваш второй пример сильно препятствует тому, чтобы вызывать вызов другого метода базового класса. В конце концов, он/она не будет использовать стандартный шаблон. Используйте этот шаблон только в том случае, если вы хотите отказать унаследователю от вызова метода базового класса.

+0

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

+0

Согласен, после повторного чтения вашего сообщения в блоге. Ред. Благодарю. –

Смежные вопросы