Методы
Методы класса и методы объекта
Различают методы класса и методы объекта, которые называют также статическими и виртуальными, соответственно. Первым аргументом метода должна быть ссылка, представляющая объект, или имя пакета. То, каким образом каждый метод обрабатывает свой первый аргумент, определяет, является ли он методом класса или методом объекта.
Статические методы применяются к целому классу, а не к отдельным его объектам. В качестве первого аргумента статическому методу передается имя класса. Типичным примером статических методов являются конструкторы. В Perl методы выполняются в пространстве имен того пакета, в котором они были определены, а не в пространстве имен пакета, в котором они вызваны. Поэтому статические методы часто свой первый аргумент игнорируют, так как и без него известно, к какому пакету метод принадлежит. Последнее не относится к конструкторам, передающим свой первый аргумент функции Ыезз () в качестве имени класса.
Методы объекта применяются к отдельному объекту. Их первым аргументом должна быть ссылка, указывающая на объект, к которому применяется данный метод. Методы объекта могут выполнять разные действия, но наиболее типичными являются действия, связанные с отображением и изменением данных, инкапсулированных в объекте. В примере 13.2 мы присвоили значения, а затем их распечатали, обращаясь к данным объекта напрямую. Таким способом мы просто продемонстрировали, что конструктор действительно возвращает ссылку, представляющую объект. В действительности это плохой способ, и применять его не рекомендуется.
В некоторых объектно-ориентированных языках программирования прямой доступ к данным объекта вообще невозможен. Объект следует рассматривать как "черный ящик", содержимое которого можно получить или изменить, только используя методы объекта. Такое ограничение помогает сохранить целостность и скрыть некоторые внутренние данные объекта. Отредактируем текст примера 13.2, дополнив его методами, которые используются для изменения и просмотра данных.
# Модуль класса Staff.pm: package Staff; require Exporter; @ISA = qw(Exporter); 8EXPORT = qw(new showdata setdata); sub new { my ($class, $data) = @_; my $self = $data; bless $self, $class; return $self; } sub showdata { my $self = SHIFT; my @keys = @_? @_: sort keys %$self; foreach $key (@keys) { print "\t$key › $self › {$key}\n"; } return $self; } sub setdata { my ($self,$data) = @_; for $i (keys %$data) { $self › {$i)=$data › {$i); } return $self; }
В данном примере по сравнению с предыдущим изменен конструктор new (). Теперь второй параметр, представленный локальной переменной $data, содержит ссылку. Эту ссылку функция bless () свяжет с классом staff, превратив в его объект. Таким образом, при помощи этого параметра можно управлять типом внутренней структуры данных, которая и представляет объект. Это может быть ссылка на хеш-массив, массив, скаляр и т. д. Параметры, передаваемые конструктору, называют переменными объекта. Они используются для того, чтобы установить начальные значения данных каждого вновь создаваемого объекта.
Если обратиться к основной программе:
#!/usr/bin/peri use Staff; $someone=new(Staff, ("имя" › "","фамилия" › ""}); setdata($someone,{"имя" › "Максим","фамилия" › "Исаев", "возраст" › 42,"занятия спортом" › "теннис"}); showdata($someone);
…то будут выведены следующие данные:
возраст › 42 занятия спортом › теннис имя › Максим фамилия › Исаев
В разных ситуациях один и тот же метод может выступать как метод класса или как метод объекта. Для этого он должен "уметь" определить тип своего первого аргумента: если аргумент является ссылкой, то метод действует как метод объекта, если именем пакета, то есть строкой, то как метод класса. Подобную информацию можно получить при помощи функции ref (). Она возвращает значение ЛОЖЬ (пустая строка), если ее аргумент не является ссылкой, то есть объектом. В противном случае функция ref () возвращает имя пакета, принадлежность к которому была для данного объекта санкционирована функцией bless ().