В классе могут быть определены методы, не предназначенные для работы с конкретными объектами. Такие методы называются методами класса или статическими методами. Для обращения к ним, так же как для обращения к конструктору, используется имя класса, а не ссылка на объект. Часто эти методы обслуживают данные, общие для всех объектов класса (то есть объявленные глобально на уровне класса). Подобные данные называются атрибутами класса. В качестве примера опишем класс Magic::Ring, где метод класса count будет использоваться для доступа к значению атрибута класса $Magic::Ring::count,
в котором будет храниться количество созданных волшебных колец.
package Magic::Ring; # класс "Магическое Кольцо"
sub new { # конструктор
my ($class, $owner) = @_; # имя класса и значение атрибута
sub owner { # метод чтения и записи атрибута owner
my $self = shift; # извлечь ссылку на объект
$self->{owner} = shift if @_; # изменить значение атрибута
return $self->{owner}; # вернуть значение атрибута
}
$Magic::Ring::count = 0; # атрибут класса: число Колец
sub count { # метод класса
return $Magic::Ring::count;
}
1; # конец описания класса Magic::Ring
В программе, использующей класс Magic::Ring, создается набор объектов. При каждом обращении к конструктору увеличивается счетчик созданных магических колец $Magic::Ring::count.
package main;
use Magic::Ring; # использовать класс "Магическое Кольцо"
my @rings = ;
for (1..3) { # "Три кольца - премудрым эльфам..."
push @rings, new Magic::Ring('эльф');
}
for (1..7) { # "Семь колец - пещерным гномам..."
push @rings, new Magic::Ring('гном');
}
for (1..9) { # "Девять - людям Средиземья..."
push @rings, new Magic::Ring('человек');
}
# "А Одно - всесильное - Властелину Мордора..."
push @rings, new Magic::Ring('Саурон');
# Сколько всего было сделано колец?
print Magic::Ring->count, "\n"; # будет выведено: 20
В стандартную библиотеку модулей Perl входит модуль Class::Struct, который облегчает жизнь программистам по описанию классов, предоставляя для объявления класса функцию struct. Эта функция генерирует описание класса в указанном пакете, включая методы для доступа к атрибутам класса. Причем помимо имени атрибута она позволяет задавать его тип с помощью разыменовывающего префикса: скаляр ($), массив (@), хэш (%), ссылка на подпрограмму (&) или объект. Насколько просто и удобно пользоваться функцией struct, можно судить по такому примеру:
use Class::Struct; # подключаем стандартный модуль
#
описываем класс Performer ("Исполнитель")
struct Performer => { # атрибуты класса:
name => '$', # "имя" - скаляр
country => '$', # "страна" - скаляр
artists => '%', # "артисты" - хэш
};
my $performer = new Performer; # создаем исполнителя
$performer->name('Pink Floyd'); # задаем значения атрибутов
Чтобы добавить к полученному описанию класса дополнительный метод, достаточно описать его в соответствующем пакете. Вот пример добавления метода Album::print и его использования в главной программе:
package Album; # переключаемся на нужный пакет
sub Album::print { # и описываем дополнительный метод
foreach my $artist (keys%{$self->performer->artists}) {
printf("\t%s - %s\n",
$artist, $self->performer->artists($artist));
}
}
package main; # переключаемся на основную программу
$album->print; # и вызываем метод объекта
В заключение рассмотрим несколько распространенных приемов для работы с классами и объектами.
Функции bless не обязательно передавать имя класса: если второго аргумента нет, она помечает объект ссылки именем текущего пакета. Поскольку bless возвращает значение своего первого аргумента, а подпрограмма возвращает последнее вычисленное значение, то минимальный конструктор может выглядеть так: