Шаг 143.
Вызов метода

    На этом шаге мы рассмотрим различные способы вызова методов.

    Существуют две синтаксические формы вызова как методов класса, так и методов объекта.

    Первая форма имеет вид:

  method class_or_pbject, parameters
например,
  $somebody = new Staff, {"имя "=>"Анна"}; # метод класса
  showdata $somebody, "имя","фамилия"; # метод объекта
  showdata {"имя"=>"Мария","возраст"=>18}; # метод объекта
  showdata new Staff "возраст"; # метод объекта
  showdata setdata new Staff, {"имя"=>"Глеб"}, "имя"; # метод объекта

    Данная форма представляет собой обычный вызов функции, который может быть вложенным в другой вызов. Первым аргументом функции является ссылка (для методов объекта) или имя пакета (для методов класса).

    В приведенном примере первая строка содержит вызов конструктора new, в котором первым (и единственным) аргументом является имя пакета.

    Вторая строка содержит вызов метода объекта, в котором первым аргументом является объект-ссылка.

    В третьей строке первый аргумент задается при помощи блока {}, возвращающего ссылку на анонимный хеш-массив. Данный хеш-массив не будет объектом, так как он не объявлен объектом класса Staff при помощи функции bless(), но синтаксически такая конструкция возможна.

    В четвертой строке метод объекта вызывается с двумя аргументами. Первым аргументом является ссылка, возвращаемая конструктором new(), вторым - строка "возраст".

    В пятой строке конструктор new создает объект, который передается в качестве первого аргумента методу setdata. Вторым аргументом метода setdata является ссылка на анонимный хеш-массив {"имя"=>"глеб"}. Метод showdata в качестве первого аргумента использует ссылку, возвращаемую методом setdata, а в качестве второго аргумента - строку "имя".

    Вторая форма обращения к методу имеет вид

  class_or_object -> method(parameters)

    Например, предыдущие вызовы могут быть записаны также в виде:

  $somebody = Staff->new({"имя"=>"Анна"});
  $somebody->showdata("имя","фамилия");
  new Staff->showdata("возраст");
  new Staff->setdata({"имя"=>"Глеб"})->showdata("имя");

    Вторая форма требует обязательного заключения аргументов в скобки.


    Замечание. Как видим, обе формы записи могут быть достаточно сложными. В разных случаях любая из них может оказаться предпочтительной в смысле читаемости текста программы. Если нет серьезных оснований против, то рекомендуем использовать вторую форму, исходя из следующих соображений.

    При использовании первой формы на том месте, где должен стоять объект или имя класса, синтаксис позволяет использовать либо имя класса, либо скалярную переменную, содержащую ссылку, либо блок {...}, возвращающий значение ссылки. Вторая форма для представления объекта позволяет использовать более сложные конструкции, например, элемент хеш-массива:

   $obj->{keyname}->method().
При употреблении первой формы могут возникнуть трудноопределимые ошибки. Например, если происходит обращение к методу в области видимости одноименной функции, то при использовании первой формы вызова компилятор может вместо метода вызвать функцию. Вторая форма подобную ошибку исключает.

    Для того чтобы вызвать метод определенного класса, следует перед именем метода указать имя пакета, как при вызове обычной подпрограммы. Например, чтобы вызвать метод, определенный в пакете Staff, следует использовать запись вида:

  $someone = new Staff;
  Staff::showdata($someone, "имя");

    В данном случае просто вызывается метод showdata из пакета Staff. Ему передается в качестве аргумента объект $someone и прочие аргументы. Если вызвать метод следующим образом:

  $someone=new Staff; 
  $someone->Staff::showdata("имя");
то это будет означать, что для объекта $someone следует сначала найти метод showdata, начав поиск с пакета Staff, а затем вызвать найденный метод с объектом $someone в качестве первого аргумента. Напомним, что с каждым пакетом ассоциируется свой массив @ISA, содержащий имена других пакетов, представляющих классы. Если интерпретатор встречает обращение к методу, не определенному в текущем пакете, он ищет этот метод, рекурсивно (то есть включая производные классы) просматривая пакеты, определенные в массиве @ISA текущего пакета. Если подобный вызов делается внутри пакета, являющегося классом, то для того, чтобы указать в качестве начала поиска базовый класс, не указывая его имя явно, можно использовать имя псевдокласса SUPER:
  $someone->SUPER::showdata("имя");

    Такая запись имеет смысл только внутри пакета, являющегося классом.

    На следующем шаге мы рассмотрим деструкторы.




Предыдущий шаг Содержание Следующий шаг