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.
Хотя мы настоятельно рекомендуем не создавать объекты с нуля, вы должны знать термин благословение. Благословлённая структура данных (также известная как "ссылка") является объектом. Иногда мы говорим, что объект был "благословлён в класс".
После того, как ссылка была благословлена, функция 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.
Вы также можете увидеть термины getter и setter. Это два типа аксессоров. Getter получает значение атрибута, а setter устанавливает его. Другой термин для setter — мутатор
Атрибуты обычно определяются как только для чтения или для чтения и записи. Атрибуты только для чтения можно задавать только при создании объекта, а атрибуты для чтения и записи можно изменять в любое время.
Значение атрибута может быть другим объектом. Например, вместо возвращения времени последней модификации как числа, класс File мог бы возвращать объект DateTime, представляющий это значение.
Возможен класс, не предоставляющий публично настраиваемые атрибуты. Не каждый класс имеет атрибуты и методы.
Полиморфизм
Полиморфизм — это сложное понятие, означающее, что объекты из двух разных классов имеют общий API. Например, у нас могут быть классы File и WebPage, которые оба имеют метод print_content(). Этот метод может создавать различный вывод для каждого класса, но они имеют общий интерфейс.
Хотя два класса могут различаться во многих отношениях, в отношении метода print_content() они одинаковы. Это означает, что мы можем попытаться вызвать метод print_content() для объекта любого из этих классов, и нам не нужно знать, к какому классу принадлежит объект!
Полиморфизм является одной из ключевых концепций объектно-ориентированного дизайна.
Наследование
Наследование позволяет вам создать специализированную версию существующего класса. Наследование позволяет новому классу повторно использовать методы и атрибуты другого класса.
Например, мы можем создать класс File::MP3, который наследует от класса File. Объект File::MP3 является более специфичным типом File. Все файлы mp3 являются файлами, но не все файлы являются файлами mp3.
Мы часто называем отношения наследования родитель-ребёнок или отношениями superclass/subclass. Иногда мы говорим, что у дочернего класса есть отношение является к родительскому классу.
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, который унаследован от 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 реализуются как хэши под капотом. Принцип инкапсуляции говорит нам, что мы не должны полагаться на это. Вместо этого мы должны использовать методы-аксессоры для доступа к данным в этом хэше. Системы объектов, которые мы рекомендуем ниже, автоматизируют создание методов-аксессоров. Если вы используете одну из них, вам никогда не нужно будет напрямую обращаться к объекту как к хэшу.
Композиция
В объектно-ориентированном коде мы часто находим, что один объект ссылается на другой объект. Это называется композицией или «имеет-а» отношением.
Ранее мы упоминали, что аксессор File класса last_mod_time может возвращать объект 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, чтобы предоставить больше функций и удобства.
Мы настоятельно рекомендуем использовать одну из этих систем. Даже самые минимальные из них устраняют много повторяющегося boilerplate. На самом деле нет веских причин для написания своих классов с нуля на Perl.
Если вас интересует внутреннее устройство этих систем, ознакомьтесь со статьей perlobj.
Moose
Moose позиционируется как «постмодернистская система объектов для Perl 5». Не пугайтесь, метка «постмодернистская» — это отсылка к описанию Лэрри Perl как «первого постмодернистского компьютерного языка».
Moose предоставляет полную современную систему ООП. Самое большое влияние — система объектов Common Lisp, но она также заимствует идеи из Smalltalk и нескольких других языков. Moose была создана Stevan Little и сильно опирается на его работу над дизайном ООП Raku.
Вот наш класс 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. -
Богатый экосистема
Существует богатый экосистема расширений
Mooseна CPAN в пространстве имен MooseX. Кроме того, многие модули на CPAN уже используютMoose, предоставляя вам много примеров для обучения. -
И многое другое
Moose— очень мощный инструмент, и мы не можем охватить здесь все его функции. Мы рекомендуем вам узнать больше, прочитав документациюMoose, начиная с Moose::Manual.
Конечно, Moose не идеален.
Moose может замедлить загрузку вашего кода. Moose сам по себе не маленький, и он выполняет много генерации кода при определении вашего класса. Эта генерация кода означает, что ваш код во время выполнения будет быстрым, но вы платите за это при первой загрузке модулей.
Эта проблема с временем загрузки может возникнуть, когда скорость запуска имеет значение, например, в командной строке скрипте или обычном CGI-скрипте, который должен загружаться каждый раз при выполнении.
Прежде чем паниковать, знайте, что многие люди используют Moose для инструментов командной строки и другого кода, чувствительного к времени запуска. Мы рекомендуем вам сначала попробовать Moose перед тем, как беспокоиться о скорости запуска.
Moose также имеет несколько зависимостей от других модулей. Большинство из них — небольшие автономные модули, некоторые из которых были выделены из Moose. Moose и некоторые из его зависимостей требуют компилятора. Если вам нужно установить программное обеспечение на систему без компилятора или если наличие любых зависимостей является проблемой, то Moose может не подойти вам.
Moo
Если вы попробуете Moose и обнаружите, что одна из этих проблем мешает вам использовать Moose, мы рекомендуем вам рассмотреть Moo далее. Moo реализует подмножество функциональности Moose в более простом пакете. Для большинства реализованных функций интерфейс конечного пользователя идентичен 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— этоMooseв лёгком варианте, и разумная альтернатива, когда 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–2023 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.38.0/perlootut