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 ядра может указать имя его класса. Эта подпрограмма возвращает имя класса объекта, если передается объект, и false в противном случае.
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-файлы.
Мы часто называем отношения наследования родитель-ребенок или отношениями superclass/subclass. Иногда мы говорим, что у ребенка есть отношение is-a с родительским классом.
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» (copyright 2004, Published by O'Reilly Media, Inc.) Damian Conway предоставляет список критериев, которые нужно использовать при принятии решения о том, подходит ли ООП для вашей задачи:
-
Разрабатываемая система большая или, вероятно, станет большой.
-
Данные можно агрегировать в очевидные структуры, особенно если в каждой структуре много данных.
-
Различные типы агрегированных данных образуют естественную иерархию, что облегчает использование наследования и полиморфизма.
-
Набор данных, на котором выполняются многие разные операции.
-
Вам нужно выполнить одни и те же общие операции над связанными типами данных, но с незначительными вариациями в зависимости от конкретного типа данных, к которому применяются операции.
-
Вполне возможно, что вам придётся добавлять новые типы данных позже.
-
Типичные взаимодействия между данными лучше всего представляются операторами.
-
Вероятность изменения реализации отдельных компонентов системы со временем.
-
Дизайн системы уже объектно-ориентированный.
-
Большое количество других программистов будет использовать ваши модули кода.
СИСТЕМЫ PERL ООП
Как мы уже упоминали ранее, встроенная система ООП 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. -
Богатый экосистема
Существует богатый экосистема расширений
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 в более простом пакете. Для большинства реализованных функций 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.28.3/perlootut