Должен ли я создать подкласс List <T>или иметь его как свойство? - PullRequest
15 голосов
/ 20 октября 2008

Я сталкивался с этой проблемой довольно часто в последние пару месяцев, в течение которых я строил эту систему. Сценарий таков: у меня есть объект такого типа, который по сути представляет собой список других объектов, но имеет некоторые другие свойства, характерные для его природы. Например:

  • Класс Tests:
    • Содержит множество Test объектов
    • Имеет свойства:
      • DefaultTimeouts
      • DefaultNumberOfTries

Должен ли я иметь этот подкласс класса List<Test> или он должен наследоваться от Object, просто имея список как свойство рядом с другими полями?

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

Ответы [ 8 ]

12 голосов
/ 20 октября 2008

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

У меня обычно просто есть свойство типа List (или IList), которое возвращает ссылку на список. Обычно вам нужно только приобрести недвижимость здесь. Вы можете контролировать доступ к списку, выбрав возврат только для чтения версии списка с помощью .AsReadOnly () или просто выставив список как IEnumerable.

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

6 голосов
/ 20 октября 2008

Подкласс из Списка . Если у вас есть универсальный список в качестве свойства, он не так хорошо инкапсулирован, как подкласс.

Если он выглядит как список и звучит как список , это, вероятно, список .

Я бы назвал это TestCollection.

1 голос
/ 20 октября 2008

При чтении ответов кажется, что ключевым вопросом является какой длины ваш объект действительно списка? Так что, возможно, хороший компромисс между опасностями наследования и отсутствием Прозрачность композиции будет заключаться в том, чтобы иметь List<Test> в качестве частного бэкэнда и раскрывать только те методы, которые будут использоваться.

1 голос
/ 20 октября 2008

Я не думаю, что у вас есть простой «список тестов», потому что вам нужно что-то большее. Я бы посоветовал вам назвать это TestSuite и сделать список как собственность. Has-a гораздо проще поддерживать по сравнению с наследованием.

В общем, я бы очень осторожно унаследовал что-то вроде List.

1 голос
/ 20 октября 2008

Наследование обычно сопоставляется с отношением "есть". Поскольку ваш контейнер является списком , но с некоторыми другими вещами я бы унаследовал от List и добавил бы ваши дополнительные свойства в ваш подкласс.

1 голос
/ 20 октября 2008

Если он буквально делает все, что сделает List, и все функции List будут действовать на объект Tests интуитивно понятным способом, который дает правильный результат, то, на мой взгляд, он должен просто подкласс List<Test>.

В противном случае у вас будет просто класс с кучей методов, которые просто вызывают метод с тем же именем в переменной List<Test> в экземпляре. Это будет просто несовершенное расширение самого класса List<Test>.

0 голосов
/ 20 октября 2008

«Пользуйся композицией, а не наследованием» - это всегда хорошее правило. Используют ли методы, которые используют этот класс, все методы List, а также те, которые вы добавляете, или только те, которые вы добавляете?

0 голосов
/ 20 октября 2008

В вашем примере вы сказали «Классовые тесты содержат много объектов Тест», а не «Классовые тесты - это коллекция объектов Тесты». IMO: нет необходимости создавать подклассы List в этом сценарии, если вам не нужен интерфейс, подобный List для этого класса.

Однако ответ действительно зависит от контекста класса Tests. Если он ведет себя как List и будет использоваться в тех контекстах, где ожидается List из объектов, наследуется от List.

Обратите внимание, что наследование сложнее поддерживать, чем состав.

Кроме того, я бы переименовал Tests в TestCollection (если вы используете подкласс List) или что-то вроде TestUnit (если он будет содержать список классов Test.

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