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 возвращает значение своего первого аргумента, а подпрограмма возвращает последнее вычисленное значение, то минимальный конструктор может выглядеть так:
sub new { # конструктор экземпляров класса
my $self = {}; # контейнер для атрибутов объекта
bless($self); # "благословить" объект ссылки
} # и вернуть ссылку (1-й аргумент bless)
При создании объекта удобно сразу задавать начальные значения его атрибутов, передавая аргументы конструктору. Если для инициализации атрибутов использовать хэш, то атрибуты можно задавать в любом порядке, а в конструкторе можно определить значения по умолчанию для незаданных атрибутов. Например, так:
my $language = Programming::Language->new(
NAME => 'Perl', # имя
VERSION => '5.8.7', # версия
AUTHOR = 'Larry Wall' # автор
);
Весьма полезно иметь в классе метод, который преобразовывает значения атрибутов объекта в строку. Такой метод обычно называется as_string или to_string и может применяться для отладочной печати состояния объекта. А если его определить в классе-"прародителе", то его можно будет применять к объектам всех унаследованных классов. Если использовать анонимный хэш для хранения значений атрибутов, то такой метод может выглядеть так: