Область действия метода и параметр Self
Заметьте, что ни в одном из предыдущих примеров конструкция: with объект do... не встречается в явном виде. Поля данных объекта легко доступны с помощью методов объекта. Хотя в исходном коде поля данных объекта и тела методов разделены, на самом деле они совместно используют одну и ту же область действия.
Именно поэтому один из методов TEmployee может содержать оператор GetTitle := Title без какого-либо квалификатора перед Title. И именно поэтому Title принадлежит тому объекту, который вызывает метод. Если объект вызывает метод, то выполняется неявный оператор with myself do method, связывающий объект и его методы в области действия.
Неявный оператор with выполняется путем передачи невидимого параметра методу всякий раз, когда этот метод вызывается. Этот параметр называется Self и в действительности является 32-разрядным указателем на экземпляр объекта, осуществляющего вызов метода. Относящийся к TEmployee метод GetRate приблизительно эквивалентен следующему:
function TEmployee.GetRate(var Self: TEmployee): integer; begin GetRate := Self.Rate; end;
Примечание: Синтаксически этот пример не совсем корректен. Он приведен только затем, чтобы дать вам более полное представление о специфической связи между объектом и его методом.
Но важно ли вам знать о существовании параметра Self? Обычно нет. Генерируемый Borland Pascal код выполняет все это автоматически. Однако в некоторых немногочисленных случаях вы можете захотеть проникнуть внутрь метода и использовать параметр Self явно.
Примечание: Явное использование параметра Self допускается, но вы должны избегать ситуаций, в которых это требуется.
Параметр Self является частью физического кадра стека при всех вызовах методов. Методы, используемые как внешние на языке Ассемблера, должны учитывать Self при получении доступа к параметрам метода в стеке.
Поля данных объекта и формальные параметры метода
Выводом из того факта, что методы и их объекты разделяют общую область действия, является то, что формальные параметры метода не могут быть идентичными любому из полей данных объекта. Это является не каким-то новым ограничением, налагаемым объектно-ориентированным программированием, а скорее теми же самыми старыми правилами области действия, которые Паскаль имел всегда. Это то же самое, что и запрет для формальных параметров процедуры быть идентичными локальным переменным этой процедуры:
procedure CrunchIt(Crunchee: MyDataRec, Crunchby, ErrorCode: integer); var A, B: char; ErrorCode: integer; begin . . .
Локальные переменные процедуры и ее формальные параметры совместно используют общую область действия и поэтому не могут быть идентичными. Вы получите сообщение "Error 4: Duplicate identifier" (Ошибка 4; Повторение идентификатора), если попытаетесь компилировать что-либо подобное, та же ошибка возникает при попытке присвоить формальному параметру метода имени поля объекта, которому данный метод принадлежит.
Обстоятельства несколько отличаются, так как помещение заголовка процедуры внутрь структуры данных является намеком на новшество в Турбо Паскале, но основные принципы области действия Паскаля не изменились.
1 2
8 8 8
| |