Обобщение UML без полиморфизма
Возможно ли иметь отношение обобщения между двумя классами, в котором подкласс добавляет новые операции, не относящиеся к суперклассу (не переопределяя, не перегружая)? Это не нарушение LSP? Мне не нужен полиморфизм, просто повторное использование кода в подклассах.
РЕДАКТИРОВАТЬ: суперкласс является абстрактным, частично определенным
2 ответа
Да, UML позволяет определять новые операции в подклассе, которых нет в суперклассе.
Это не обязательно нарушение принципа замены Лискова. Экземпляры подкласса могут быть заменены там, где ожидаются экземпляры суперкласса (но вам не нужно использовать это).
Однако убедитесь, что экземпляры вашего подкласса действительно могут считаться экземплярами суперкласса. Если это не так, и вы просто хотите повторно использовать код, обобщение не является правильным решением.
Пример: Класс StringCollection имеет операцию сортировки. Теперь вы хотите повторно использовать эту операцию сортировки в новом классе под названием FileManager. FileManager - это не просто StringCollection, поэтому не следует использовать обобщение. Вместо этого вы можете использовать зависимость "использовать" (FileManager использует StringCollection) или композицию (FileManager содержит StringCollection).
Подкласс может добавлять новые элементы, такие как операции или атрибуты, в более конкретный класс, которые не определены в более общем классе. Также более конкретный класс может переопределять функции, скрывать атрибуты и реализовывать абстрактные операции. Полагаю, LSP означает принцип замещения Лискова.
Если это нарушено или нет, это не столько синтаксический вопрос, на который может ответить UML; вместо этого это семантический вопрос о рассуждении о значении классов. Рассмотрим классический пример, является ли квадрат более общим, чем прямоугольник. Или наоборот? Но синтаксически обе одинаковы, как и многие другие менее сомнительные иерархии.
Вопрос о полиморфизме немного сложен. UML не использует этот термин явно. Но в нем четко указано, что каждый экземпляр более конкретного класса (ifier) также является экземпляром более общего класса (ifier) и наследует все его функции. Это означает, что не существует синтаксиса UML, который позволяет наследовать только реализацию.
Но вы можете легко решить эту проблему, применив подходящий шаблон проектирования. Вопрос недостаточно конкретен, чтобы судить, что образец ведьмы является наиболее подходящим, но хорошими кандидатами являются стратегия или образец моста. Тогда у вас есть полное наследование между классами, реализующими ваши алгоритмы (и они могут быть частными или менее видимыми - в зависимости от языка), но классы, которые используются клиентами, не имеют отношения обобщения и, следовательно, не могут использоваться полиморфным способом..