function THourly.GetPayAMount : Real;
var
OverTime: Integer;
begin
Overtime := Time – OvertimeThreshold;
if Overtime > 0 then
GetPayAmount := RoundPay(OvertimeThreshold * Rate +
Rate OverTime * OvertimeFactor * Rate)
else
GetPayAmount := RoundPay(Time * Rate)
end;
Метод TSalaried.GetPayAmount намного проще; в нем ставка
делится на число выплат:
function TSalaried.GetPayAmount : Real;
begin
GetPayAmount := RoundPay(Rate / PayPeriods);
end;
Если взглянуть на метод TCommissioned.GetPayAmount, то будет видно, что он вызывает TSalaried.GetPayAmount, вычисляет комиссионные и прибавляет их к величине, возвращаемой методом TSalaried. GetPayAmount.
function TСommissioned.GetPayAmount : Real;
begin
GetPayAmount := RoundPay(TSalaried.GetPayAmount +
Commission * SalesAmount);
end;
Важное замечание: хотя методы могут быть переопределены, поля данных переопределяться не могут. После того как было определено поле данных в иерархии объекта, никакой дочерний тип не может определить поле данных в точности с таким же именем.
Наследование до некоторой степени изменяет правила совместимости типов в Borland Pascal. Помимо всего прочего, порожденный тип наследует совместимость типов всех своих порождающих типов.
Эта расширенная совместимость типов принимает три формы:
1) между реализациями объектов;
2) между указателями на реализации объектов;
3) между формальными и фактическими параметрами.
Однако очень важно помнить, что во всех трех формах совместимость типов расширяется только от потомка к родителю. Другими словами, дочерние типы могут свободно использоваться вместо родительских, но не наоборот.
Например, TSalaried является потомком TEmployee, а ТСош-missioned – потомком TSalaried. Помня об этом, рассмотрим следующие описания:
tyрe
PEmрloyee = ^TEmployee;
PSalaried = ^TSalaried;
PCommissioned = ^TCommissioned;
var
AnEmрloyee: TEmployee;
ASalaried: TSalaried;
PCommissioned: TCommissioned;
TEmployeePtr: PEmрloyee;
TSalariedPtr: PSalaried;
TCommissionedPtr: PCommissioned;
При данных описаниях справедливы следующие операторы
присваивания:
AnEmрloyee :=ASalaried;
ASalaried := ACommissioned;
TCommissionedPtr := ACommissioned;
Порождающему объекту можно присвоить экземпляр любого из его порожденных типов. Обратные присваивания недопустимы.
Эта концепция является новой для Pascal, и вначале, возможно, трудновато запомнить, в каком порядке следует совместимость типов. Необходимо думать следующим образом: источник должен быть в состоянии полностью заполнить приемник. Порожденные типы содержат все, что содержат их порождающие типы благодаря свойству наследования. Поэтому порожденный тип имеет либо в точности такой же размер, либо (что чаще всего и бывает) он больше своего родителя, но никогда не бывает меньше. Присвоение порождающего (родительского) объекта порожденному (дочернему) могло бы оставить некоторые поля порожденного объекта неопределенными, что опасно и поэтому недопустимо.
В операторах присваивания из источника в приемник будут копироваться только поля, являющиеся общими для обоих типов. В операторе присваивания:
AnEmployee:= ACommissioned;
Только поля Name, Title и Rate из ACommissioned будут скопированы в AnEmployee, так как только эти поля являются общими для TCommissioned и TEmployee. Совместимость типов работает также между указателями на типы объектов и подчиняется тем же общим правилам, что и для реализаций объектов. Указатель на потомка может быть присвоен указателю на родителя. Если дать предыдущие определения, то следующие присваивания указателей будут допустимыми:
TSalariedPtr:= TCommissionedPtr;
TEmployeePtr:= TSalariedPtr;
TEmployeePtr:= PCommissionedPtr;
Следует помнить, что обратные присваивания недопустимы!