Разрыв полиморфизма против подклассов с неиспользованными унаследованными членами - PullRequest
2 голосов
/ 31 октября 2009

Если я использую наследование и позже осознаю, что одному подклассу нужен метод или поле, которое недоступно, я должен объявить это в базовом классе и не реализовывать его в других подклассах, или я должен объявить его в этом один подкласс?

Если я решу объявить метод в подклассе, я больше не смогу обрабатывать все полиморфно. С другой стороны, если я решу поместить его в базовый класс, я получу множество подклассов, не реализующих свойство или метод. Я видел примеры в .net Framework, где выбран «не реализованный» подход. Какой лучший путь?

Ответы [ 6 ]

1 голос
/ 31 октября 2009

Метод не принадлежит базовому классу, если каждый возможный производный класс не имеет соответствующей реализации.

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

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

Обновление

Я бы хотел отозвать свое предыдущее заявление. Как указал Уэйн Хартман, если бы это было правдой, то System.IO.Stream также сломал бы LSP. Правило гласит, что вы не можете генерировать новые исключения из метода в подтипе. Похоже, это не относится к абстрактным методам, поскольку они не имеют никакой реализации.

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

Я также согласен, что иногда частичная реализация для согласованности уместна.

1 голос
/ 31 октября 2009

Если только у одного подкласса есть метод X, конечно, вы не можете вызывать X полиморфно по определению. Разумно ли, чтобы X существовал в суперклассе (и, следовательно, повсюду), но в большинстве случаев был неактивным? Иногда это так, иногда вам просто нужно переосмыслить всю иерархию классов, т. Е. Почему do вы хотите вызывать X полиморфно, даже там, где он может не существовать (или, в лучшем случае, быть неактивным)? Невозможно ответить, не зная много, много больше о вашем конкретном случае использования!

0 голосов
/ 31 октября 2009

Для этого вам нужно ответить на несколько вопросов о намерениях вашего API.

  1. Как использовать ваш API: Если ваши потребители API почти всегда ссылаются на ваш базовый класс, то, возможно, имеет смысл поместить его в базовый класс.
  2. Если метод, который вы пытаетесь реализовать, применим практически ко всем производным классам, которые могут реализовать эту функциональность, поместите его в базовый класс.

Рассмотрим System.IO.Stream, это абстрактный класс с абстрактными методами для операций поиска, имеет смысл не иметь производных от чего-то вроде System.IO.SeekableStrem только для того, чтобы получить функциональность поиска, пользователи API должны обращаться только к Stream.

0 голосов
/ 31 октября 2009

Я всегда предпочитал использовать исключения стиля NotImplemented для кода, который еще не закончен. Я бы никогда не использовал это лично, чтобы добавить больше методов в базовый класс.

0 голосов
/ 31 октября 2009

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

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

0 голосов
/ 31 октября 2009

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

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