Совместимость типов объектов
Наследование до некоторой степени изменяет правила совмести- мости типов в Borland Pascal. Помимо всего прочего, порожденный тип наследует совместимость типов всех своих порождающих типов. Эта расширенная совместимость типов принимает три формы:
- между реализациями объектов; - между указателями на реализации объектов; - между формальными и фактическими параметрами.
Однако очень важно помнить, что во всех трех формах совмес- тимость типов расширяется только от потомка к родителю. Другими словами, дочерние типы могут свободно использоваться вместо роди- тельских, но не наоборот.
В модуле WORKERS.TPU TSalaried является потомком TEmployee, а TCommissioned - потомком TSalaried. Помня об этом, рассмотрим следующие описания:
tyрe PEmрloyee = ^TEmployee; PSalaried = ^TSalfried; PCommissioned = ^TCommissioned; var AnEmрloyee: TEmployee; ASalaried: TSalaried; PCommissioned: TCommissioned; TEmployeePtr: PEmрloyee; TSalariedPtr: PSalaried; TCommissionedPtr: PCommissioned;
При данных описаниях справедливы следующие операторы присва- ивания:
AnEmрloyee :=ASalaried; ASalaried := ACommissioned; TCommissionedPtr := ACommissioned;
Примечание: Порождающему объекту можно присвоить эк- земпляр любого из его порожденных типов.
Обратные присваивания недопустимы.
Эта концепция является новой для Паскаля, и в начале, воз- можно, вам будет трудновато запомнить, в каком порядке следует совместимость типов. Думайте следующим образом: источник должен быть в состоянии полностью заполнить приемник. Порожденные типы содержат все, что содержат их порождающие типы благодаря свойству наследования. Поэтому порожденный тип имеет либо в точности такой же размер, либо (что чаще всего и бывает) он больше своего роди- теля, но никогда не бывает меньше. Присвоение порождающего (роди- тельского) объекта порожденному (дочернему) могло бы оставить не- которые поля порожденного объекта неопределенными, что опасно и поэтому недопустимо.
В операторах присваивания из источника в приемник будут ко- пироваться только поля, являющиеся общими для обоих типов. В опе- раторе присваивания:
AnEmрloyee := ACommissioned;
Только поля Name, Title и Rate из ACommissioned будут скопи- рованы в AnEmрloyee, т.к. только эти поля являются общими для TCommissioned и TEmployee. Совместимость типов работает также между указателями на типы объектов и подчиняется тем же общим правилам, что и для реализаций объектов. Указатель на потомка мо- жет быть присвоен указателю на родителя. Если дать предыдущие оп- ределения, то следующие присваивания указателей будут допустимы- ми:
TSalariedPtr := TCommissionedPtr; TEmployeePtr := TSalariedPtr; TEmployeePtr := PCommissionedPtr;
Помните, что обратные присваивания недопустимы.
Формальный параметр (либо значение, либо параметр-перемен- ная) данного объектного типа может принимать в качестве фактичес- кого параметра объект своего же типа или объекты всех дочерних типов. Если определить заголовок процедуры следующим образом:
рrocedure CalcFedTax(Victim: TSalaried);
то допустимыми типами фактических параметров могут быть TSalaried или TCommissioned, но не тип TEmployee. Victim также может быть параметром-переменной. При этом выполняются те же правила совмес- тимости.
Замечание: Имейте в виду, что между параметрами-значениями и параметрами-переменными есть коренное отличие. Параметр-значение является указателем на действительный, посылаемый в качестве па- раметра объект, тогда как параметр-переменная является только ко- пией фактического параметра. Более того, эта копия включает толь- ко те поля, которые входят в тип формального параметра-значения. Это означает, что фактический параметр буквально преобразуется к типу формального параметра. Параметр-переменная больше напоминает приведение к образцу, в том смысле, что фактический параметр ос- тается неизменным.
Аналогично, если формальный параметр является указателем на тип объекта, фактический параметр может быть указателем на этот тип объекта или на любой дочерний тип. Пусть дан заголовок проце- дуры:
рrocedure Worker.Add (AWorker: PSalaried);
тогда допустимыми типами фактических параметров могут быть PSalaried или PCommissioned, но не тип PEmрloyee.