perlootut
СОДЕРЖАНИЕ
- ИМЯ
- ДАТА
- ОПИСАНИЕ
- ОСНОВЫ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО ПРОГРАММИРОВАНИЯ
- СИСТЕМЫ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО ПРОГРАММИРОВАНИЯ В PERL
- ЗАКЛЮЧЕНИЕ
ИМЯ
perlootut - Руководство по объектно-ориентированному программированию на Perl
ДАТА
Этот документ был создан в феврале 2011 года, а последняя крупная редакция была в феврале 2013 года.
Если вы читаете это в будущем, то возможно, что состояние дел изменилось. Мы рекомендуем вам начать с чтения документа perlootut в последней стабильной версии Perl, а не этой версии.
ОПИСАНИЕ
Этот документ предоставляет введение в объектно-ориентированное программирование на Perl. Он начинается с краткого обзора концепций объектно-ориентированного проектирования. Затем он представляет несколько различных систем ООП из CPAN, которые строятся поверх возможностей Perl.
По умолчанию встроенная система ООП Perl очень минимальна, оставляя вам большую часть работы. Эта минимальность имела смысл в 1994 году, но за прошедшие годы после Perl 5.0 мы увидели множество общих шаблонов в Perl ООП. К счастью, гибкость Perl позволила развиться богатому экосистеме систем Perl ООП.
Если вы хотите узнать, как работает Perl ООП под капотом, документ perlobj объясняет подробности.
Этот документ предполагает, что вы уже знакомы с основами синтаксиса Perl, типами переменных, операторами и вызовами подпрограмм. Если вы еще не понимаете эти концепции, пожалуйста, сначала прочтите perlintro. Вы также должны прочитать документы perlsyn, perlop и perlsub.
ОСНОВЫ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО ПРОГРАММИРОВАНИЯ
Большинство объектных систем разделяют ряд общих концепций. Вероятно, вы уже слышали такие термины, как «класс», «объект», «метод» и «атрибут». Понимание этих концепций значительно упростит чтение и написание объектно-ориентированного кода. Если вы уже знакомы с этими терминами, все равно стоит просмотреть этот раздел, так как в нем каждая концепция объясняется в терминах реализации ООП в Perl.
Система ООП Perl основана на классах. Класс-ориентированное ООП довольно распространено. Оно используется в Java, C++, C#, Python, Ruby и во многих других языках. Существуют и другие парадигмы объектно-ориентированного программирования. JavaScript — наиболее популярный язык, использующий другую парадигму. Система ООП JavaScript основана на прототипах.
Объект
Объект — это структура данных, которая объединяет данные и подпрограммы, которые работают с этими данными. Данные объекта называются атрибутами, а подпрограммы — методами. Объект можно рассматривать как существительное (человек, веб-сервис, компьютер).
Объект представляет собой отдельную дискретную вещь. Например, объект может представлять собой файл. Атрибуты для объекта файла могут включать его путь, содержимое и время последней модификации. Если мы создали объект для представления /etc/hostname на машине с именем "foo.example.com", путь этого объекта будет "/etc/hostname", его содержимое — "foo\n", а время последней модификации — 1304974868 секунд с начала эпохи.
Методы, связанные с файлом, могут включать rename() и write().
В Perl большинство объектов являются хешами, но рекомендуемые системы ООП избавляют вас от необходимости беспокоиться об этом. На практике лучше всего рассматривать внутреннюю структуру данных объекта как непрозрачную.
Класс
Класс определяет поведение категории объектов. Класс — это имя категории (например, «Файл»), и класс также определяет поведение объектов в этой категории.
Все объекты принадлежат определенному классу. Например, наш объект /etc/hostname принадлежит к классу File. Когда мы хотим создать конкретный объект, мы начинаем с его класса и создаем или инициализируем объект. Конкретный объект часто называют экземпляром класса.
В Perl любой пакет может быть классом. Разница между пакетом, который является классом, и тем, который им не является, основана на том, как используется пакет. Вот наше «объявление класса» для класса File:
package File; В Perl нет специального ключевого слова для создания объекта. Однако большинство модулей ООП в CPAN используют метод с именем new() для создания нового объекта:
my $hostname = File->new(
path => '/etc/hostname',
content => "foo\n",
last_mod_time => 1304974868,
); (Не беспокойтесь об операторе ->, он будет объяснен позже.)
Благословение
Как мы уже говорили, большинство объектов Perl являются хешами, но объект может быть экземпляром любого типа данных Perl (скаляр, массив и т. д.). Преобразование обычной структуры данных в объект выполняется путем благословения этой структуры данных с помощью функции Perl bless.
Хотя мы настоятельно рекомендуем вам не создавать объекты с нуля, вы должны знать термин благословение. Благословенная структура данных (также «ссылочный объект») — это объект. Иногда мы говорим, что объект был «благословлен в класс».
После того, как referent был благословлен, функция blessed из модуля ядра Scalar::Util может сообщить нам имя его класса. Эта подпрограмма возвращает имя класса объекта, если ей передан объект, и ложь в противном случае.
use Scalar::Util 'blessed';
print blessed($hash); # undef
print blessed($hostname); # File Конструктор
Конструктор создает новый объект. В Perl конструктор класса — это просто другой метод, в отличие от некоторых других языков, которые предоставляют синтаксис для конструкторов. Большинство классов Perl используют new в качестве имени своего конструктора:
my $file = File->new(...); Методы
Вы уже узнали, что метод — это подпрограмма, которая работает с объектом. Вы можете рассматривать метод как действия, которые объект может выполнять. Если объект — это существительное, то методы — это глаголы (сохранить, напечатать, открыть).
В Perl методы — это просто подпрограммы, которые находятся в пакете класса. Методы всегда пишутся таким образом, чтобы получать объект в качестве первого аргумента:
sub print_info {
my $self = shift;
print "This file is at ", $self->path, "\n";
}
$file->print_info;
# The file is at /etc/hostname То, что делает метод особенным, — это способ его вызова. Оператор стрелки (->) указывает Perl на то, что мы вызываем метод.
При вызове метода Perl обеспечивает передачу вызывающего объекта в качестве первого аргумента. Вызывающий объект — это красивое название для объекта слева от стрелки. Вызывающий объект может быть именем класса или объектом. Мы также можем передавать дополнительные аргументы в метод:
sub print_info {
my $self = shift;
my $prefix = shift // "This file is at ";
print $prefix, ", ", $self->path, "\n";
}
$file->print_info("The file is located at ");
# The file is located at /etc/hostname Атрибуты
Каждый класс может определять свои атрибуты. При создании экземпляра объекта мы присваиваем значения этим атрибутам. Например, каждый объект File имеет путь. Атрибуты иногда называются свойствами.
В Perl нет специального синтаксиса для атрибутов. Под капотом атрибуты часто хранятся в качестве ключей в базовом хеше объекта, но об этом не нужно беспокоиться.
Мы рекомендуем обращаться к атрибутам только через методы-аксессоры. Это методы, которые могут получать или устанавливать значение каждого атрибута. Мы видели это ранее в примере print_info(), который вызывает $self->path.
Вы также можете встретить термины геттер и сеттер. Это два типа аксессоров. Геттер получает значение атрибута, а сеттер устанавливает его. Еще один термин для сеттера — мутатор
Атрибуты обычно определяются как только для чтения или для чтения и записи. Атрибуты только для чтения можно установить только при первом создании объекта, а атрибуты для чтения и записи могут быть изменены в любое время.
Значение атрибута может быть другим объектом. Например, вместо возвращения времени последней модификации как числа, класс File мог бы вернуть объект DateTime, представляющий это значение.
Возможен класс, который не предоставляет никаких публично устанавливаемых атрибутов. Не каждый класс имеет атрибуты и методы.
Полиморфизм
Полиморфизм — это красочный способ сказать, что объекты из двух разных классов разделяют API. Например, у нас могут быть классы File и WebPage, которые оба имеют метод print_content(). Этот метод может производить различные результаты для каждого класса, но у них общий интерфейс.
Хотя два класса могут отличаться по многим параметрам, когда дело доходит до метода print_content(), они одинаковы. Это означает, что мы можем попытаться вызвать метод print_content() на объекте любого из этих классов, и нам не нужно знать, к какому классу принадлежит объект!
Полиморфизм — одна из ключевых концепций объектно-ориентированного проектирования.
Наследование
Наследование позволяет вам создать специализированную версию существующего класса. Наследование позволяет новому классу повторно использовать методы и атрибуты другого класса.
Например, мы можем создать класс File::MP3 , который унаследует от File. Объект File::MP3 — это более конкретный тип File. Все mp3-файлы — файлы, но не все файлы — mp3-файлы.
Мы часто называем отношения наследования родитель-ребенок или родитель-потомок отношениями.
Иногда мы говорим, что ребенок имеет отношение «является» с родительским классом.
File — это суперкласс File::MP3, а File::MP3 — подкласс File.
package File::MP3;
use parent 'File'; Модуль parent — один из нескольких способов, которые предоставляет Perl для определения отношений наследования.
Perl поддерживает множественное наследование, что означает, что класс может наследовать от нескольких родителей. Хотя это возможно, мы настоятельно рекомендуем этого не делать. В общем случае, вы можете использовать роли для реализации всего, что можно сделать с множественным наследованием, но более чистым способом.
Обратите внимание, что нет ничего плохого в определении нескольких подклассов для данного класса. Это и обычное, и безопасное решение. Например, мы можем определить классы File::MP3::FixedBitrate и File::MP3::VariableBitrate для различения различных типов файлов mp3.
Переопределение методов и разрешение методов
Наследование позволяет двум классам совместно использовать код. По умолчанию каждый метод в родительском классе также доступен в дочернем. Дочерний класс может явно переопределить метод родительского класса, чтобы предоставить собственную реализацию. Например, если у нас есть объект File::MP3, у него есть метод print_info() из класса File.
my $cage = File::MP3->new(
path => 'mp3s/My-Body-Is-a-Cage.mp3',
content => $mp3_data,
last_mod_time => 1304974868,
title => 'My Body Is a Cage',
);
$cage->print_info;
# The file is at mp3s/My-Body-Is-a-Cage.mp3 Если бы мы хотели включить в приветствие заголовок файла mp3, мы могли бы переопределить метод:
package File::MP3;
use parent 'File';
sub print_info {
my $self = shift;
print "This file is at ", $self->path, "\n";
print "Its title is ", $self->title, "\n";
}
$cage->print_info;
# The file is at mp3s/My-Body-Is-a-Cage.mp3
# Its title is My Body Is a Cage Процесс определения того, какой метод следует использовать, называется разрешением методов. Perl сначала обращается к классу объекта (в данном случае File::MP3). Если этот класс определяет метод, то используется версия метода этого класса. Если нет, Perl последовательно проверяет каждый родительский класс. У класса File::MP3 единственный родитель — File. Если File::MP3 не определяет метод, но File его определяет, тогда Perl вызывает метод из File.
Если File унаследован от DataSource, а DataSource унаследован от Thing, Perl будет продолжать искать вверх по цепочке наследования, если это необходимо.
Возможен явный вызов родительского метода из дочернего:
package File::MP3;
use parent 'File';
sub print_info {
my $self = shift;
$self->SUPER::print_info();
print "Its title is ", $self->title, "\n";
} Часть SUPER:: сообщает Perl искать метод print_info() в цепочке наследования класса File::MP3. Когда он находит родительский класс, реализующий этот метод, метод вызывается.
Мы упоминали множественное наследование ранее. Главная проблема множественного наследования заключается в том, что оно значительно усложняет разрешение методов. Смотрите perlobj для получения более подробной информации.
Инкапсуляция
Инкапсуляция — это концепция, согласно которой объект является непрозрачным. Когда другой разработчик использует ваш класс, ему не нужно знать как он реализован, ему нужно знать только что он делает.
Инкапсуляция важна по нескольким причинам. Во-первых, она позволяет отделить публичный API от внутренней реализации. Это означает, что вы можете изменить реализацию без нарушения API.
Во-вторых, хорошо инкапсулированные классы легче подклассировать. В идеале подкласс использует те же API для доступа к данным объекта, что и родительский класс. На практике подклассирование иногда требует нарушения инкапсуляции, но хороший API может свести необходимость в этом к минимуму.
Ранее мы упоминали, что большинство объектов Perl реализуются в виде хэшей внутри. Принцип инкапсуляции указывает, что мы не должны полагаться на это. Вместо этого мы должны использовать методы-акцессоры для доступа к данным в этом хэше. Системы объектно-ориентированного программирования, которые мы рекомендуем, автоматизируют генерацию методов-акцессоров. Если вы используете одну из них, вам никогда не придётся напрямую обращаться к объекту как к хэшу.
Композиция
В объектно-ориентированном коде мы часто сталкиваемся с ситуацией, когда один объект ссылается на другой объект. Это называется композицией или «имеет» отношением.
Ранее мы упоминали, что метод-аксессор last_mod_time класса File может возвращать объект DateTime. Это прекрасный пример композиции. Мы можем пойти ещё дальше и сделать методы-акцессоры path и content возвращающими объекты. Тогда класс File будет состоять из нескольких других объектов.
Роли
Роли — это то, что класс делает, а не то, что он является. Роли относительно новы для Perl, но стали довольно популярными. Роли применяются к классам. Иногда говорят, что классы используют роли.
Роли — это альтернатива наследованию для обеспечения полиморфизма. Предположим, что у нас есть два класса, Radio и Computer. Оба обладают включёнными/выключёнными переключателями. Мы хотим смоделировать это в наших определениях классов.
Мы могли бы заставить оба класса унаследовать от общего родителя, например, Machine, но не все машины имеют включённо/выключённые переключатели. Мы могли бы создать родительский класс, названный HasOnOffSwitch, но это будет очень искусственно. Радиоприёмники и компьютеры не являются специализациями этого родителя. Этот родитель — довольно бессмысленное изобретение.
Именно здесь на помощь приходят роли. Создать роль HasOnOffSwitch и применить её к обоим классам очень разумно. Эта роль будет определять известный API, например, методы turn_on() и turn_off().
Perl не имеет встроенного способа выражения ролей. В прошлом люди просто мирились с использованием множественного наследования. В наши дни есть несколько хороших вариантов на CPAN для использования ролей.
Когда использовать ООП
Объектно-ориентированное программирование не является лучшим решением для каждой задачи. В «Perl Best Practices» (авторство 2004 г., издательство O'Reilly Media, Inc.) Damian Conway предлагает список критериев для решения, подходит ли ООП для вашей задачи:
-
Разрабатываемая система большая или, вероятно, станет большой.
-
Данные можно сгруппировать в очевидные структуры, особенно если данных в каждой структуре много.
-
Различные типы данных образуют естественную иерархию, что облегчает использование наследования и полиморфизма.
-
Над одним набором данных применяются многочисленные разные операции.
-
Вам нужно выполнять одни и те же общие операции над родственным типом данных, но с незначительными вариациями, зависящими от конкретного типа данных, к которому применяются операции.
-
Вероятно, вам придётся добавить новые типы данных позже.
-
Типичные взаимодействия между данными лучше всего представлены операторами.
-
Реализация отдельных компонентов системы, вероятно, будет меняться со временем.
-
Конструкция системы уже ориентирована на объекты.
-
Вашим кодом модулей будут пользоваться многочисленные программисты.
СИСТЕМЫ PERL OO
Как мы уже упоминали, встроенная система ООП Perl очень минимальна, но достаточно гибкая. На протяжении многих лет многие люди разработали системы, которые строятся на базе встроенной системы Perl, чтобы обеспечить больше функций и удобства.
Мы настоятельно рекомендуем использовать одну из этих систем. Даже самые минимальные из них устраняют много повторяющегося шаблонного кода. На самом деле нет веской причины писать свои классы с нуля в Perl.
Если вы заинтересованы в деталях работы этих систем, ознакомьтесь с perlobj.
Moose
Moose позиционирует себя как «постмодернистская система объектов для Perl 5». Не пугайтесь, ярлык «постмодернистская» — отсылка к описанию Лари Perl как «первого постмодернистского языка программирования».
Moose предоставляет полную современную систему ООП. Самое большое влияние на него оказала система объектов Common Lisp, но он также заимствует идеи из Smalltalk и нескольких других языков. Moose был создан Стивеном Литлом и в значительной степени опирается на его работу над дизайном ООП Perl 6.
Вот наш класс File с использованием Moose.
package File;
use Moose;
has path => ( is => 'ro' );
has content => ( is => 'ro' );
has last_mod_time => ( is => 'ro' );
sub print_info {
my $self = shift;
print "This file is at ", $self->path, "\n";
} Moose предоставляет ряд функций:
-
Декларативное удобочитаемое обозначение
Mooseобеспечивает слой декларативного «удобочитаемого обозначения» для определения классов. Это обозначение — просто набор экспортированных функций, которые упрощают и делают более понятным объявление работы вашего класса. Это позволяет описать что представляет собой ваш класс, вместо того, чтобы говорить Perl, как реализовать ваш класс.Подпрограмма
has()объявляет атрибут, аMooseавтоматически создаёт акцессоры для этих атрибутов. Она также позаботится о создании для вас методаnew(). Этот конструктор знает об объявленных вами атрибутах, поэтому вы можете установить их при создании нового объектаFile. -
Встроенные роли
Mooseпозволяет определять роли так же, как и классы:package HasOnOffSwitch; use Moose::Role; has is_on => ( is => 'rw', isa => 'Bool', ); sub turn_on { my $self = shift; $self->is_on(1); } sub turn_off { my $self = shift; $self->is_on(0); } -
Миниатюрная система типов
В приведенном выше примере видно, что мы передали
isa => 'Bool'вhas()при создании атрибутаis_on. Это сообщаетMoose, что этот атрибут должен быть булевым значением. Если мы попытаемся установить его в неверное значение, наш код выдаст ошибку. -
Полный интроспекция и манипуляции
Встроенные возможности интроспекции Perl довольно минимальны.
Mooseопирается на них и создаёт полный слой интроспекции для ваших классов. Это позволяет задавать вопросы, например, «Какие методы реализует класс File?». Это также позволяет изменять ваши классы программно. -
Самодостаточность и расширяемость
Mooseописывает себя с помощью собственного API интроспекции. Помимо того, что это интересный трюк, это означает, что вы можете расширятьMooseс помощьюMoose. -
Богатая экосистема
На CPAN есть богатая экосистема расширений для
Mooseпод пространством имен MooseX. Кроме того, многие модули на CPAN уже используютMoose, предоставляя много примеров для обучения. -
Множество других функций
Moose— очень мощный инструмент, и мы не можем охватить здесь все его возможности. Мы рекомендуем вам узнать больше, прочитав документациюMoose, начиная с Moose::Manual.
Конечно, Moose не идеален.
Moose может сделать ваш код медленнее в загрузке. Moose сам по себе не маленький, и он выполняет много генерации кода при определении вашего класса. Эта генерация кода означает, что ваш код в момент выполнения работает как можно быстрее, но вы платите за это при первой загрузке модулей.
Эта задержка при загрузке может быть проблемой, когда время запуска имеет значение, например, в скриптах командной строки или «простых» CGI-скриптах, которые должны загружаться каждый раз при выполнении.
Прежде чем паниковать, знайте, что многие используют Moose для утилит командной строки и другого чувствительного к времени запуска кода. Мы рекомендуем вам сначала попробовать Moose , прежде чем беспокоиться о скорости запуска.
Moose также имеет несколько зависимостей от других модулей. Большинство из них — небольшие автономные модули, некоторые из которых были выделены из Moose. Moose сам по себе, а также некоторые его зависимости, требуют компилятора. Если вам нужно установить ваше программное обеспечение на систему без компилятора или если наличие любых зависимостей является проблемой, то Moose может вам не подойти.
Moo
Если вы попробуете Moose и обнаружите, что одна из этих проблем препятствует использованию Moose, мы рекомендуем вам рассмотреть Moo далее. Moo реализует подмножество функциональности Moose в более простом пакете. Для большинства реализованных функций API конечного пользователя идентичен API Moose, что означает, что вы можете довольно легко переключиться с Moo на Moose.
Moo не реализует большинство API интроспекции Moose, поэтому при загрузке модулей он часто работает быстрее. Кроме того, ни одна из его зависимостей не требует XS, поэтому его можно установить на машинах без компилятора.
Одним из самых привлекательных свойств Moo является его межплатформенная совместимость с Moose. Когда кто-то пытается использовать API интроспекции Moose для класса или роли Moo, он прозрачно преобразуется в класс или роль Moose. Это упрощает интеграцию кода, использующего Moo, в базу кода Moose и наоборот.
Например, класс Moose может наследовать от класса Moo с помощью extends или использовать роль Moo с помощью with.
Авторы Moose надеются, что однажды Moo можно будет сделать устаревшим, усовершенствовав Moose достаточно, но пока он предоставляет достойную альтернативу Moose.
Class::Accessor
Class::Accessor — полная противоположность Moose. Он предоставляет очень мало функций и не является самодостаточным.
Однако он очень прост, написан на чистом Perl и не имеет зависимостей, не относящихся к ядру. Он также предоставляет API «похожий на Moose» по требованию для поддерживаемых функций.
Несмотря на то, что он не делает многого, он всё же предпочтительнее написания собственных классов с нуля.
Вот наш класс File с Class::Accessor:
package File;
use Class::Accessor 'antlers';
has path => ( is => 'ro' );
has content => ( is => 'ro' );
has last_mod_time => ( is => 'ro' );
sub print_info {
my $self = shift;
print "This file is at ", $self->path, "\n";
} Флаг импорта antlers сообщает Class::Accessor, что вы хотите определить свои атрибуты, используя синтаксис, похожий на синтаксис Moose. Единственный параметр, который вы можете передать has, это is. Мы рекомендуем использовать этот синтаксис, похожий на Moose, если вы выбираете Class::Accessor, так как это означает, что у вас будет более плавный путь обновления, если вы впоследствии решите перейти на Moose.
Как и Moose, Class::Accessor генерирует методы доступа и конструктор для вашего класса.
Class::Tiny
И наконец, у нас есть Class::Tiny. Этот модуль полностью оправдывает своё название. Он имеет невероятно минимальный API и абсолютно не зависит от каких-либо современных версий Perl. Тем не менее, мы считаем его намного удобнее, чем написание собственного объектно-ориентированного кода с нуля.
Вот наш класс File ещё раз:
package File;
use Class::Tiny qw( path content last_mod_time );
sub print_info {
my $self = shift;
print "This file is at ", $self->path, "\n";
} Вот и всё!
С помощью Class::Tiny, все методы доступа являются чтением и записью. Он генерирует для вас конструктор, а также методы доступа, которые вы определили.
Вы также можете использовать Class::Tiny::Antlers для синтаксиса, похожего на Moose.
Role::Tiny
Как мы упоминали ранее, роли предоставляют альтернативу наследованию, но Perl не имеет встроенной поддержки ролей. Если вы решите использовать Moose, он поставляется с полноценной реализацией системы ролей. Однако, если вы используете один из наших других рекомендуемых объектно-ориентированных модулей, вы всё ещё можете использовать роли с Role::Tiny
Role::Tiny предоставляет некоторые из тех же функций, что и система ролей Moose, но в гораздо меньшем пакете. Наиболее примечательно, что он не поддерживает никакого объявления атрибутов, поэтому вам придётся это делать вручную. Тем не менее, он полезен и хорошо работает с Class::Accessor и Class::Tiny
Обзор систем ОО
Вот краткий обзор доступных вариантов:
-
Moose— максимальный вариант. Он обладает множеством функций, большой экосистемой и активной пользовательской базой. Мы также кратко рассмотрели Moo.Moo— этоMooseLite и разумная альтернатива, когда Moose не подходит для вашего приложения. -
Class::Accessorделает значительно меньше, чемMoose, и является хорошей альтернативой, если вы считаетеMooseчрезмерно сложным. Он существует довольно долго и хорошо протестирован. Он также имеет минимальный режим совместимостиMoose, что упрощает переход сClass::AccessorнаMoose. -
Class::Tiny— это абсолютный минимальный вариант. Он не имеет зависимостей и почти не имеет синтаксиса. Это хороший вариант для очень минимальной среды и для быстрого создания чего-либо без необходимости беспокоиться о деталях. -
Используйте
Role::TinyсClass::AccessorилиClass::Tiny, если вы задумываетесь о множественном наследовании. Если вы используетеMoose, он поставляется со своей собственной реализацией системы ролей.
Другие системы ОО
На CPAN существует множество других объектно-ориентированных модулей, помимо рассмотренных здесь, и вам, вероятно, придётся столкнуться с одним или несколькими из них, если вы работаете с чужим кодом.
Кроме того, во многих местах код реализует все объектно-ориентированные функции «вручную», используя только встроенные возможности объектно-ориентированного программирования Perl. Если вам нужно поддерживать такой код, вы должны прочитать perlobj, чтобы понять, как именно работают встроенные объектно-ориентированные возможности Perl.
ЗАКЛЮЧЕНИЕ
Как мы уже говорили, минимальная система объектно-ориентированного программирования Perl привела к изобилию систем ОО на CPAN. Хотя вы можете вернуться к основам и написать свои классы вручную, на самом деле нет причин для этого в современных версиях Perl.
Для небольших систем Class::Tiny и Class::Accessor оба предоставляют минимальные объектные системы, которые позаботятся о базовом коде за вас.
Для более крупных проектов Moose предоставляет богатый набор функций, которые позволят вам сосредоточиться на реализации бизнес-логики. Moo предоставляет хорошую альтернативу Moose, когда вам нужно много функций, но требуется более быстрое время компиляции или нужно избежать XS.
Мы рекомендуем вам поэкспериментировать и оценить Moose, Moo, Class::Accessor и Class::Tiny, чтобы выяснить, какая система ОО подходит именно вам.
© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.30.3/perlootut