2008-11-28 8 views
2

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

Если у меня есть класс Parent-A с абстрактным методом. Там будет всего 2 ребенка. Если Child-B реализует AbstractMethodA, но Child-B не работает так, как он не применяется.

Должен ли я

  1. Удалить абстрактное ключевое слово из родителей и использовать виртуальный или динамический?
  2. Предоставьте пустую реализацию метода.
  3. Предоставить реализацию, которая вызывает ошибку, если вызвана.
  4. Игнорировать предупреждение.

Редактировать: Спасибо за все ответы. Это подтвердило мое подозрение, что этого не должно произойти. После дальнейшего исследования выясняется, что методы вообще не использовались, поэтому я полностью их удалил.

ответ

9

Если AbstractMethodA не относится к Child-B, то Child-B не должен наследовать от родителя-A.

Или взять противоположный, если Child-B наследует от родителя-A, а AbstractMethodA не относится к ребенку, то он также не должен находиться в родительском.

Помещенный метод в Parent-A, вы говорите, что метод применяется к родительскому-A и всем его дочерним элементам. Это то, что наследование означает, и если вы используете его для обозначения чего-то другого, вы столкнетесь с серьезным спором с вашим компилятором.

[Edit - сказанное, ответ Mladen Prajdic в порядке, если этот метод применяется, но ничего не должен делать для одного или нескольких классов. Метод, который ничего не делает, это ИМО не то же самое, что метод, который не применим, но, возможно, мы не имеем в виду то же самое, что «не применяется».

Другой метод - реализовать метод в Child -B в любом случае, но если бы он делал что-то решительное, как всегда, возвращал неудачу или выдавал исключение или что-то в этом роде. Он работает, но его следует рассматривать как нечто похожее, а не чистое, потому что это означает, что абоненты должны знать, что у них есть то, что они обрабатывают как Parent-A, действительно ребенок-B и поэтому они не должны называть AbstractMethodA. В основном вы отбросили полиморфизм, который является основным преимуществом наследования ОО. Лично я предпочитаю делать это таким образом, имея реализацию исключения в базовом классе, потому что тогда дочерний класс не может «случайно» плохо себя вести, «забыв» реализовать метод вообще. Он должен реализовать его, и если он реализует его, чтобы он не работал, он делает это явно. Плохая ситуация должна быть шумной.

0

сделать его виртуальным пустым в базовом классе и переопределить его в дочерних элементах.

0

Вы можете использовать интерфейсы. Затем Child-A и Child-B могут реализовывать различные методы и до сих пор наследовать от Parent-A. Интерфейсы работают как абстрактные методы, поскольку они заставляют класс реализовывать их.

2

Если реализация в потомках не является обязательной, то вы должны пойти на 1 + 2 (т.е. пустого виртуального метода в предке)

0

Если некоторые подклассы (B1, B2, ...) A используются для другого подмножества своих методов, чем другие (C1, C2, ...), можно сказать, что A можно разбить на B и C.

Я не слишком хорошо знаю Delphi (совсем нет :)), но я подумал, что так же, как, например, в Java и COM класс может «реализовывать» несколько интерфейсов. В C++ это может быть достигнуто только путем умножения наследования абстрактных классов.

Более конкретный: я бы создал два абстрактных класса (с абстрактными методами) и изменил дерево наследования.

Если это невозможно, обходным путем может быть «Адаптер»: промежуточный класс A_nonB_ со всеми введенными путями B (и дает предупреждение при их вызове) и A_nonC_. Затем измените дерево наследования, чтобы решить вашу проблему: B1, B2, ... наследовать от A_nonC_ и C1, C2, ... наследовать от A_NonB_.

1

Я думаю, что, вообще говоря, вы не должны наследовать от абстрактного класса, если вы не в состоянии реализовать все абстрактные методы в первую очередь, но я понимаю, что есть ситуации, когда это все еще делает senseto (см. класс Stream и его реализации).

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

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

Обязательный пример кода:

[Obsolete("This class does not implement this method", true)] 
public override string MyReallyImportantMethod() 
{ 
    throw new NotImplementedException("This class does not implement this method."); 
} 
Смежные вопросы