Spec-Zone.ru › Perl 5.36

perlootut

СОДЕРЖАНИЕ

  • НАЗВАНИЕ
  • ДАТА
  • ОПИСАНИЕ
  • ФУНДАМЕНТАЛЬНЫЕ ПОНЯТИЯ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО ПРОГРАММИРОВАНИЯ
    • Объект
    • Класс
      • Благословение
      • Конструктор
    • Методы
    • Атрибуты
    • Полиморфизм
    • Наследование
      • Переопределение методов и разрешение методов
    • Инкапсуляция
    • Композиция
    • Роли
    • Когда использовать ООП
  • СИСТЕМЫ ООП В PERL
    • Moose
      • Moo
    • Class::Accessor
    • Class::Tiny
    • Role::Tiny
    • Резюме систем ООП
    • Другие системы ООП
  • ЗАКЛЮЧЕНИЕ

НАЗВАНИЕ

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.

Мы часто называем отношения наследования родитель-ребёнок или отношениями родителя/ребёнка. Иногда говорим, что у ребёнка есть отношение 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 OO

Как мы упоминали ранее, встроенная система ООП Perl очень минимальна, но также довольно гибкая. На протяжении многих лет многие люди разрабатывали системы, которые строятся поверх встроенной системы Perl, чтобы предоставить больше функций и удобств.

Мы настоятельно рекомендуем использовать одну из этих систем. Даже самые минимальные из них устраняют много повторяющегося кода. Нет веских причин для написания ваших классов с нуля в Perl.

Если вас интересуют внутренности этих систем, см. perlobj.

Moose

Moose позиционируется как «постмодернистская система объектов для Perl 5». Не пугайтесь, «постмодернистская» метка — это отсылка к описанию Лари Perl как «первого постмодернистского языка программирования для компьютеров».

Moose предоставляет полную современную систему ООП. Его главным влиянием является система объектов Common Lisp, но он также заимствует идеи из Smalltalk и нескольких других языков. Moose был создан Стеваном Литтлом и сильно опирается на его работу над дизайном ООП 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.

  • Богатый экосистема

    На 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

    Moose — это максимальный вариант. У него много функций, большая экосистема и активная пользовательская база. Мы также кратко рассмотрели Moo. Moo — это облегчённый вариант Moose, и разумная альтернатива, когда Moose не подходит для вашего приложения.

  • Class::Accessor

    Class::Accessor делает намного меньше, чем Moose, и является хорошей альтернативой, если вы считаете Moose слишком сложным. Он существует уже давно и хорошо проверен. Он также имеет минимальный режим совместимости с Moose, что облегчает переход от Class::Accessor к Moose.

  • Class::Tiny

    Class::Tiny — это абсолютный минимальный вариант. Он не имеет зависимостей и практически без синтаксиса для изучения. Это хороший вариант для суперминимальной среды и для быстрого создания чего-либо без необходимости беспокоиться о деталях.

  • Role::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–2021 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.36.0/perlootut

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API