Главная страница Случайная страница Разделы сайта АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Инкапсуляция
Объединение в объекте методов и данных называется инкапсуляцией. При работе с объектами необходимо создавать достаточное количество методов, обеспечивающих работу со всеми полями данных, чтобы не возникала необходимость обращаться непосредственно к полям. Под полиморфизмом понимают возможность замещения методами потомка методов родителя с теми же именами и параметрами. В типе TStudent объявлена процедура Init, которая наследуется от предка, но ее необходимо переопределить, так как инициализируется дополнительное поле Ball: Procedure TStudent.Init; Begin TPerson.Init (Nm, Dg, Sv); Ball: = Bl; End; Вместо того, чтобы непосредственно присваивать значения наследованным полям, таким как Name, Dolgn и Stavka, проще использовать метод инициализации объекта TPerson. Для описания наследуемых методов может использоваться зарезервированное слово Inherited (унаследованный). В этом случае описание метода TStudent.Init будет выглядеть: Procedure TStudent.Init; Begin Inherited Init (Nm, Dg, Sv); Ball: = Bl; End; Смысл переопределения метода не меняется. Любое изменение в родительском методе автоматически сказывается на методах-потомках. Для определения другой категории служащих – сотрудников института – введем описание объекта TStaff: TStaff = Object (TPerson) Private Bonus: Real; Public Procedure Init (Nm, Dg: String; Sv, Bn: Real); Function GetSum: Real; Procedure ShowSum; Procedure ShowAll; End; Предположим, размер выплаты стипендии зависит от среднего балла студента следующим образом: Function TStudent.GetSum: Real; Begin If Ball > 4.6 Then GetSum: = 1.5 * Stavka Else GetSum: = Stavka End; Сотрудникам института к размеру ставки прибавляется размер премиальных выплат: Function TStaff.GetSum: Real; Begin GetSum: = Stavka + Bonus End; Методы могут быть переопределены, но поля переопределяться не могут. После того, как поле данных в иерархии объекта определено, никакой дочерний тип не может определить поле данных с таким же именем. В методах не использовалась явная конструкция With... Do.... Поля данных объекта являются доступными для методов этого объекта. Будучи разделенными в исходной программе, тела методов и поля данных совместно используют одну и ту же область действия. Статические методы. Виртуальные методы Описания объектов TPerson, TStudent, TStaff и TTeacher содержат процедуры ShowSum и ShowAll. Для объекта TStudent эта процедура может выглядеть следующим образом: Procedure TStudent.ShowSum; Begin Writeln (GetSum); End; Для объекта TТeacher эта процедура имеет тот же самый вид: Procedure TТeacher.ShowSum; Begin Writeln (GetSum); End; TТeacher может унаследовать ShowSum от TStaff, а TStaff от TStudent. Поскольку все методы одинаковы, возникает вопрос: нужно ли описывать эти методы для всех объектов? Дело в том, что пока копия метода ShowSum не будет помещена в область действия TТeacher для подавления метода ShowSum объекта TStaff, метод будет работать неправильно. Если TТeacher вызывает метод ShowSum объекта TStaff, то и функция GetSum, используемая в методе, будет принадлежать объекту TStaff. Зарплата будет рассчитана без учета количества часов. Все описанные методы, относящиеся к типам объектов TPerson, TStudent, TStaff и TTeacher, являются статическими методами. Такое название методов связано с тем, что размещение соответствующих ссылок на них осуществляется еще на этапе компиляции. Действия компилятора при обработке методов объектов, составляющих некую иерархию, таковы: 1. При вызове метода компилятор устанавливает тип объекта, вызывающего метод. 2. Установив тип, компилятор ищет метод в пределах типа объекта. Найдя его, компилятор назначает вызов этого метода. 3. Если указанный метод не найден, то компилятор начинает рассматривать тип непосредственного прародителя и ищет метод, имя которого вызвано, в пределах этого прародительского типа. В случае, если метод с таким именем найден, вызов заменяется на вызов метода прародителя. 4. Если искомый метод отсутствует в типе следующего прародителя, то компилятор переходит к типу следующего прародителя. И так далее. Если метод прародителя вызывает другие методы, то последние также будут методами прародителя.
|