Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Перекрытие методов
Рассмотрим класс для описания животных, способных издавать звуки: type TPet = class procedure Speak; end;
procedure TPet.Speak; begin Beep; // ничего особенного – просто звуковой сигнал end; Потомки TPet – классы TDog и TCat – тоже способны «издавать звуки», но делают это по-своему. Ситуация является достаточно типичной при проектировании иерархии классов: наследник имеет такие же методы как и предок, но реализует их своим способом. ООП даёт возможность описать в классе-потомке метод с тем же именем, что и в классе-предке, но с собственной реализацией. Это называется перекрытие (замещение) методов: type TDog = class(TPet) procedure Speak; // перекрытие метода TPet.Speak end;
TCat = class(TPet) procedure Speak; // перекрытие метода TPet.Speak end;
procedure TDog.Speak; begin writeln('Bow-wow') end;
procedure TCat.Speak; begin writeln('Mew') end; При перекрытии методов их сигнатуры (то есть количество и тип параметров) могут различаться. Если дочерний класс не перекрывает метод предка, а добавляет новый метод с тем же именем, необходимо воспользоваться директивой overload, чтобы явно указать на перегрузку. Естественно, такие методы должны различаться сигнатурой: type TCatWithVolume = class(TCat) // не перекрыли TCat.Speak, а добавили метод с параметром procedure Speak(Volume: Integer); overload; end; Разберём вопрос о перекрытии полей класса. Классическое ООП не допускает подобного. Однако в Object Pascal дочерний класс может объявить поле с тем же именем, что и поле в родительском классе, но с другим типом. В этом случае методы в дочернем классе будут работать с новым полем, методы в родительском классе – со старым. На практике такая возможность практически не используется, так как способна основательно запутать и проектировщика, и пользователей класса. Достаточно часто метод класса-потомка не заменяет действия в методе класса-предка, а дополняет их. Чтобы не дублировать код, в методе класса-потомка можно вызвать метод класса-предка. Для вызова перекрытых методов ближайшего класса-предка применяется конструкция inherited имя-метода-класса–предка. Если имя и параметры вызываемого у предка метода совпадают с именем и параметрами вызывающего метода, достаточно записать только ключевое слово inherited: procedure TCat.Speak; begin inherited; // вызов TPet.Speak – звуковой сигнал writeln('Mew') end; Если в непосредственном предке метод, вызываемый через inherited, отсутствует, компилятор проводит поиск такого метода по иерархии классов вплоть до корневого класса. Если метод не найден, никаких действий не предпринимается. В иерархии классов работа конструктора класса-потомка, как правило, начинается с вызова конструктора класса-предка для корректной инициализации полей предка. Добавим конструктор в класс TEmployee (используется вариант класса TPerson с простым конструктором): type TEmployee = class(TPerson) public ... constructor Create; end;
constructor TEmployee.Create; begin inherited; // можно написать inherited Create // fAge: = 1, fName: = 'Person' fName: = 'Employee' end; Для деструкторов в иерархии классов действует правило, согласно которому вызов унаследованного деструктора происходит в конце работы класса-потомка.
|