- •Предисловие
- •Введение Эволюция разработки программного обеспечения
- •Технологии программирования
- •Основные понятия объектно-ориентированного программирования
- •Инкапсуляция
- •Свойства
- •Векторные свойства
- •Создание и уничтожение объектов
- •Конструкторы
- •Деструкторы
- •Наследование
- •Свойства
- •Конструкторы и деструкторы класса-предка
- •Полиморфизм, виртуальные и динамические методы
- •Статическое перекрытие виртуальных методов
- •Виртуальное перекрытие конструкторов и деструкторов
- •Абстрактные методы
- •Области видимости
- •Перекрытие и переопределение свойств
- •Перекрытие методов доступа к свойствам
- •Приведение объектных типов, операторы as и is
- •Агрегация
- •События
- •Процедурный тип
- •Создание события
- •Инициаторы события
- •Делегирование
- •Внутреннее устройство объекта
- •Указатели на класс
- •Виртуальные конструкторы
- •Методы класса
- •Обработка исключительных ситуаций
- •Операторы try...Except и try...Finally
- •Исключительные ситуации как объекты
- •Перегрузка методов
- •Перегрузка виртуальных методов
- •Параметры по умолчанию
- •Основы объектно-ориентированного анализа и проектирования
- •Объектно-ориентированная модель
- •Классы и объекты
- •Заключение Применение объектно-ориентированного программирования
- •Библиографический список
-
Перегрузка методов
В Object Pascal, начиная с четвертой версии Borland Delphi, появилась разновидность методов, называемых перегружаемыми. Перегрузка нужна, чтобы произвести одинаковые или похожие действия с разнотипными данными. В предыдущих примерах перегрузка использовалась для определения у класса нескольких конструкторов.
Перегружаемыми называют одноименные методы класса, различающиеся набором формальных параметров. Компилятор выбирает, какой именно метод будет вызван по тому, какой набор фактических параметров передается при его вызове.
Для того, что бы объявить метод перегружаемым в Object Pascal используется директива overload. Перегружать методы можно как внутри одного класса, так и в классах-потомках:
Type T1 = class(TObject) procedure Test(i: integer); overload; procedure Test(s: string); overload; end; T2 = class(T1) procedure Test(r: real); overload; end;
Рассмотрим пример. У двух классов, связанных отношением наследования есть разнотипные данные, и есть метод, который устанавливает значение этих данных SetData. Сначала попытаемся обойтись без использования механизма перегрузки:
Type TOb1 = class (TObject) r: real; procedure SetData(AValue: real); end;
TOb2 = class(TOb1) c: char; procedure SetData(AValue: char); end;
...
Procedure Test; var T1: TOb1; T2: TOb2; begin T1 := TOb1.Create; T2 := TOb2.Create; T1.SetData(1.1); //допустимо //T2.SetData(1.1); //не допустимо T2.SetData(‘1’); //допустимо ... T1.Free; T2.Free; end;
Строка T2.SetData(1.1) вызовет ошибку компиляции. Для компилятора внутри класса TOb2, к которому принадлежит объект Т2, метод SetData с параметром типа real перекрыт статически, методом с параметром типа char. Следовательно, такой путь неприменим. Рассмотрим, какие возможны выходы. Первый – дать методам разные имена. Но если методов не два, а сто, то может возникнуть путаница. Второй – сделать метод SetData перегружаемым.
В этом случае пример будет выглядеть так:
Type TOb1 = class(TObject) r: real; procedure SetData(AValue: real); overload; end;
TOb2 = class(TOb1) c: char; procedure SetData(AValue: char); overload; end;
...
Procedure Test; var T1: TOb1; T2: TOb2; begin T1 := TOb1.Create; T2 := TOb2.Create; T1.SetData(1.0); //допустимо T2.SetData(1.0); //допустимо T2.SetData(‘1’); //допустимо ... T1.Free; T2.Free; end;
Объявив метод SetData перегружаемым, в программе можно использовать обе его реализации одновременно. Компилятор будет различать, какой из них вызвать, по типу передаваемого параметра.
Объявить перегружаемые методы SetData можно и внутри одного класса:
Interface type TDat = class private r: real; i: integer; s: string; ... public procedure SetData(AValue: real); overload; procedure SetData(AValue: integer); overload; procedure SetData(AValue: string); overload; ... end;
implementation procedure TDat.SetData(AValue: real); begin r := AValue; end;
procedure TDat.SetData(AValue: integer); begin i := AValue; end;
procedure TDat.SetData(AValue: string); begin s := AValue; end;
...
procedure Test; var T: TDat; begin T := TDat.Create; ... T.SetData(1.0); //допустимо T.SetData(1); //допустимо T.SetData(‘1’); //допустимо ... T.Free; end;
В этом примере в разных случаях будет установлено значение разных полей.
Если перегружаемый метод является функцией, т.е. возвращает значение, то при перегрузке метода тип возвращаемого значения можно изменить. Но изменение только типа функции не является достаточным для перегрузки метода. Поскольку это не позволяет компилятору определить, какой именно метод следует вызывать. Следующий пример вызовет ошибку компиляции:
Type TOb1 = class(TObject) function F(): real; overload; ... end;
TOb2 = class(TOb1) //function F(): char; overload; //ошибка компиляции, поскольку изменения только //типа возвращаемого значения недостаточно для перегрузки ... end;