Наследование в ООТ — основные понятия, поведение методов при наследовании
Наследование (субклассирование) — это способность одного класса использовать характеристики другого. Оно использует отношение «вид чего-либо» между двумя классами. Этот простой принцип означает, что если вы хотите создать новый класс, лишь немного отличающийся от известного, то нет необходимости в переписывании заново полей и методов уже существующих у класса-предка.
Предок (ancestor) — это класс, представляющий свои возможности и характеристики другим классам через механизм наследования.
Потомок(descendant) — Класс, который использует характеристики другого класса посредством наследования.
Непосредственный предок, от которого данный класс прямо происходит, называется родителем (parent).
• Пользовательский класс может иметь только одного родителя.
• Особенностью наследования является то, что:
— оно расширяет возможности в том смысле, что любой класс-потомок имеет доступ или наследует практически все ресурсы (методы, поля и свойства) родительского класса и всех его предков до самого верхнего уровня иерархии, т.е. до класса TObject. Наследование поддерживает повторное использование кода у потомков;
— наследование позволяет потомку усовершенствовать родительский класс, сделав его более специализированным. В определении класса-потомка указываются лишь новые методы, замещающие методы и новые поля.
• В классах-потомках можно переносить объявления из одного раздела в другой, с большей видимостью, кроме раздела Private, из которого в разделы с большей видимостью не переносят.
Наследование полей
• Поля, унаследованные от класса-родителя, располагаются перед новыми.
• В классе-потомке можно заместить наследуемый метод, но нельзя отказаться от наследования какого-либо поля.
• В классе-потомке можно объявить одноименное поле другого типа и этим скрыть прямой доступ к переопределенному полю. Тем не менее доступ будет возможен к обоим полям:
— к новому — напрямую:
Obj.<поле>;
— к переопределенному — используя приведение типов: TParentClass(Obj). <поле>;
• При переопределении поля можно перенести его объявление в раздел класса с другой видимостью, однако нельзя перенести объявления полей из раздела Private.
Поведение методов при наследовании
По тому, какие действия происходят при вызове, методы делятся на четыре группы: Static (статические), Virtual (виртуальные), Dynamic (динамические), Abstract (абстрактные). Одной из проблем наследования является диспетчеризация вызовов методов объектов, под которой понимается то, каким образом приложение будет определять какой код требуется выполнить при вызове того или иного метода. Во многом это определяется видом метода.
Статические методы
По умолчанию все методы класса являются статическими. Транслятор разрешает вызовы статических методов на фазе трансляции. К моменту запуска программы адреса вызова статических методов уже известны и, поэтому они вызываются быстрее других. Этот механизм называют еще ранним связыванием (early binding).
Примечания:
• Статический метод можно скрыть, если определить новый виртуальный или динамический метод с тем же именем.
• Статический метод можно переопределить, если в наследуемом классе объявить новый статический метод с тем же именем. Можно изменять при переопределении и список параметров.
• Доступ к скрытому или переопределенному статическому методу возможен с помощью механизма приведения типов:
TParentClass(Obj). <метод>;
• Вызов статического метода определяется исключительно типом объектной переменной. Тип самого объекта, на который эта переменная в данный момент ссылается, не имеет значения, т.е. при вызове статического метода фактический класс объекта игнорируется. Если в программе встречается обращение Obj.StaticMethod, где Obj — переменная TClassType, то генерируется вызов метода TCIassType.StaticMethod или ближайший StaticMethod, наследуемый классом TCIassType. Переменная Obj может ссылаться на один из потомков класса, производного от TClassType, в котором определен свой StaticMethod, т.е. фактически будет использоваться экземпляр дочернего класса. Тем не менее будет вызван именно TClassType.StaticMethod, т.е. для дочернего класса будет вызываться метод родителя