Выбор между наследованием и перечислением - PullRequest
0 голосов
/ 20 декабря 2018

У меня есть класс Land:

class Land{
    double latitude;
    double longitude;
}

Земля может быть одного из 3 типов - крутая, обычная и влажная.Единственное различие между ними заключается в том, что когда «танк» посещает эти земли, он несет различные затраты в зависимости от типа земли.

Теперь, если мне нужно создать перечисление LandType:

enum LandType{
    STEEPY, PLAIN, WET
}

и использоватьэто как поле в классе земли?

Или я должен создать 3 производных класса земли: SteepyLand, PlanLand, WetLand?Каковы решающие факторы, чтобы сделать правильный выбор?

1 Ответ

0 голосов
/ 21 декабря 2018

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

Но если, например, для влажной земли требуются дополнительные и специфические атрибуты, вы можете использовать наследование для создания более специализированного типа данных и, следовательно, включения полиморфизма.То же самое, когда Land будет иметь операции, которые требуют определенной реализации или являются специфическими для определенной LandType, вы должны использовать наследование.

Также, если вам нужна расширяемость, рассмотрите наследование: есть перечисления, которые не изменятся вбудущее, например, enum 'Playback' может содержать значения 'Next', 'Previous' и 'Current', и они не изменятся, потому что других нет.В этом случае выражение типа земли с помощью enum работает хорошо.Но мы можем представить множество различных «типов объектов», так что изменение или расширение перечисления с большей вероятностью произойдет.Чтобы избежать этой модификации LandType, вы можете вместо этого реализовать новый подтип.Например, многие фреймворки и библиотеки делают это для своих исключений: вместо изменения внутреннего класса для предоставления новых флагов вы вынуждены предоставлять свое пользовательское исключение, наследуя его от общедоступного базового типа, например Exception.

Отображение итераций над вашими Land объектами, для которых вы хотите исключить любые Land, где LandType - «Мокрый», ваш результат будет «Крутой» и «Простой».Но при добавлении нового значения 'Rocky' к вашему перечислению LandType и не меняя все ваши фильтры, вы получите 'Steepy', 'Plain' и 'Rocky'.Это может повредить ваш код везде, где «Рокки» не ожидается, или его следует исключить, так как вы исключили «Мокрый» из своих результатов.Вы не хотите менять существующий код каждый раз, когда добавляете новый LandType.Таким образом, конкретная реализация нового типа Land поможет избежать взлома существующего кода.

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

...