Возможности наследования и полиморфизм
Рассмотрим три типовых варианта применения наследования. Положим, у нас есть родительский класс с двумя атрибутами (элементами данных) ра1 и ра2 и двумя операциями (элементами-функциями) ор_а1() и ор_а2(). Этот родитель хочет, чтобы потомок был его точной копией. В этом случае потомок владеет теми же (родительскими) атрибутами и операциями, поэтому секции атрибутов и операций потомка пусты (рис. 16.21). Нет нужды показывать их содержимое — по умолчанию все знают, что там находится «родительское богатство».
Рис. 16.21. Наследник является точной копией родителя |
Возможности наследования и полиморфизм |
449 |
Однако второй потомок этого родителя-консерватора взбунтовался и реализовал идею: «я, папа, от твоего наследства не отказываюсь, но хочется чего-то новенького, дополнительного». В итоге наследник добавил себе два атрибута ра3, ра4 и одну новую операцию ор_а3() (рис. 16.22). Его секции атрибутов и операций не пусты — в них прописаны новые названия. |
Рис. 16.22. Наследник наращивает количество атрибутов и операций |
Наконец, третий потомок оказался самым требовательным: «я и нового хочу, и от старого отказываюсь (правда, лишь частично)». При реализации этого тезиса он разместил в себе новые атрибуты ра5, ра6, новую операцию ор_а4() и переопределил родительскую операцию ор_а2(), изменив ее содержание (рис. 16.23). Переопределение родительских операций приводит к тому, что в дереве наследования классов появляются операции с одинаковым заголовком и разными телами — все вместе они образуют так называемую полиморфную операцию. Такая операция имеет много форм, то есть реализаций. На рис. 16.11 уже приводился пример полиморфной операции площадь(). Она появилась в силу переопределения классами-потомками Круг и Квадрат родительской операции, операции класса Точка. Возвращаясь к обсуждению полиморфизма в главе 13, следует сказать, что здесь вводится полиморфизм подтипов. Для обращения к одной из форм полиморфной операции удобно использовать динамическое связывание. Оно создается на основе полиморфной переменной- указателя. Полиморфная переменная-указатель привязывается к родительскому классу, после чего может адресовать любой из экземпляров классов-наследников. Например, мы объявляем указатель Точка *фигура_укз; // полиморфная переменная-указатель на родительский класс после чего с помощью оператора фигура_укз -> площадь( ); |
450 Глава 16. Объектно-ориентированное и аспектно-ориентированное программирование |
получаем возможность обратиться к экземпляру как класса Точка, так и класса Круг или Квадрат. Конечно, предварительно нужно занести в указатель адрес искомого экземпляра, а это можно сделать в любой момент периода выполнения программы. |
Рис. 16.23. Наследник наращивает количество атрибутов, операций и переопределяет родительскую операцию |