5. Абстракции, полиморфизм и множественное наследование
Виды дизайна классов
Конкретный класс
Почему sealed или final (Java, C++) имеет смысл?
Абстрактный класс
Полиморфизм – способность иметь много форм (is-a): Фигура имеет много форм – круг, квадрат и т.п., но сама по себе фигура – это
Пример 100% необходимости полиморфизма: Гетерогенные (Heterogenous) коллекции
Приведение к предку (Up-casting)
Разница между override и new методами
Явное приведение типа (Down-casting)
Наследование и агрегация – ключевые блоки ООД
Адаптер через наследование, или через агрегацию
Множественное наследование
Проблемы множественного наследования классов в С++
Избыточность (Redundancy)
И снова неоднозначность
C++ имеет костыль “виртуальное наследование”
Интерфейсы C# и Java
Интерфейсы C# 8.0
836.79K
Категория: ПрограммированиеПрограммирование

5_Абстракции,_полиморфизм_и_множественное_наследование

1. 5. Абстракции, полиморфизм и множественное наследование

2. Виды дизайна классов

• Конкретный (concrete), запрещает наследование: String,
ComplexNumber
• Абстрактный (abstract), корень иерархии: Animal
• Узловой (node), промежуточный в иерархии: Crocodile
• Адаптер (adapter) – адаптирует поведение нужного класса

3. Конкретный класс

• Отображает простую и понятную концепцию: строка, вектор, дата,
комплексное число, структуры…
• Имеет реализацию всех методов
• Подобные классы, если используются во многих задачах, встраиваются
в язык или библиотеки
• Автономны
• Рекомендуется запретить наследование:
• Чтобы не нарушить поведением наследников его четкую концепцию
• В целях производительности
• Запретить доступ к “чувствительным” данным
• Запрет переиспользования реализации класса третьей стороной

4. Почему sealed или final (Java, C++) имеет смысл?

Рекомендация: если класс не
сконструирован специально для
наследования, запретите его.

5. Абстрактный класс

6. Полиморфизм – способность иметь много форм (is-a): Фигура имеет много форм – круг, квадрат и т.п., но сама по себе фигура – это

абстракция
• Конструкторы
нужны для
инициализации
полей
наследниками
• Их нельзя
вызвать из
другого кода
• Делайте их
protected!

7. Пример 100% необходимости полиморфизма: Гетерогенные (Heterogenous) коллекции

Коллекции, которые хранят элементы с общим предком
Shape[] shapes = new Shape[2];
shapes[0] = new Square(200, 200);
shapes[1] = new Circle(300, 300);
foreach (Shape shape in shapes)
shape.Draw();

8. Приведение к предку (Up-casting)

• Shape s = new Circle(100, 100);
При этом s будет содержать ссылку на
объект типа Circle.
s.Draw() => Drawing a CIRCLE at 100,100
• Всегда производится неявно (implicit),
статически и безопасно (Circle ведет
себя как Shape)

9. Разница между override и new методами

New сообщает, что полиморфизм надо “отключить”
s.Draw() => Drawing a SHAPE at 100,100

10. Явное приведение типа (Down-casting)

• Имея ссылку на родителя, как обратится к методам наследника?
• Принудительно приводим объект к классу наследника во время
выполнения
• Не безопасно (unsafe), т.к. приводимый объект может быть не из
этой иерархии, а ошибка будет только во время выполнения

11. Наследование и агрегация – ключевые блоки ООД

Пример паттерн
Адаптер
https://www.bestprog.net/r
u/2020/09/24/patternsexamples-ofimplementation-of-theadapter-pattern-in-c-ru/

12. Адаптер через наследование, или через агрегацию

• Клиент сформулировал
свои требования к
удаленной системе в
виде интерфейса
ITarget. Работа через
него - упрощает
клиента.
• Удаленная система
реализована в виде
класса Adaptee. Он
непохож на ITarget.
• Нужен класс-адаптер

13. Множественное наследование

• Класс наследует от нескольких родителей
• Предпочтительно, чтобы родители были ортогональны друг другу
(без одинаковых методов)
• Удобно, когда разным клиентам нашего класса нужна разная
функциональность
• Удобно для reuse
• Усложняет код:
• В одном классе смешивается несколько обязанностей
• Один класс зависит от нескольких других
• Пересечение методов

14. Проблемы множественного наследования классов в С++

• getAge() – вызывает
неоднозначность
(ambiguity)
• Нет правил приоритета
родителей, поэтому
наследник должен сам явно
определить свой getAge()

15. Избыточность (Redundancy)

• Student содержит часть от
Person
• Employee содержит часть от
Person
• StudentEmp содержит часть от
двух Person

16. И снова неоднозначность

Student меняет
реализацию метода
родителя, а Employee
нет

17. C++ имеет костыль “виртуальное наследование”

• Если
наследование
родителей
отмечено virtual,
то их общий
наследник не
наследует
двойную копию
прадеда
• Но такая отметка
ставится только
постфактум,
когда проблема
уже проявилась,
заранее ее не
предугадать!

18.

19. Интерфейсы C# и Java

• Помогают наследовать
разноплановое поведение
• Лишены проблем с
наследованием
реализации и данных
• Удачная альтернатива
множественному
наследованию
https://dotnettutorials.net/les
son/multiple-inheritancerealtime-example-in-csharp/

20. Интерфейсы C# 8.0

• Имеют реализацию методов по
умолчанию
• Отличаются от абстрактных классов
отсутствием полей и конструкторов
• Нужны для расширения старых
интерфейсов
https://dev.to/lolle2000la/why-interface-defaultimplementations-in-c-are-a-great-thing-52nj
English     Русский Правила