=encoding utf8

=for comment
Последовательное форматирование этого файла осуществляется с:
  perl ./Porting/podtidy pod/perlootut.pod

=head1 NAME/НАИМЕНОВАНИЕ

perlootut - Руководство по Объектно-ориентированному Программированию в Perl

=head1 ДАТЫ

Этот документ был создан в феврале 2011 года и последняя на данный момент 
основная ревизия - февраль 2013 года.

Если вы читаете эти строки, находясь в будущем, вполне возможно, что  
описываемые здесь вещи изменились. Поэтому рекомендуем вам читать perlootut
последней стабильной версии Perl.

=head1 ОПИСАНИЕ

Этот документ является введением в объектно-ориентированное программирование 
в Perl. Сначала вкратце описываются концепции, лежащие в основе 
объектно-ориентированного дизайна. Затем приводится несколько различных 
ОО систем из L<CPAN|http://search.cpan.org>,  построенных поверх возможностей,
имеющихся в Perl.

Встроенная в Perl ОО система по умолчанию крайне минималистична, предоставляя 
вам самому выполнить большую часть работы. Этот минимализм имел много 
смысла в 1994, но в годы, последовавшие за появлением Perl 5.0, мы наблюдали
появление ряда распространенных паттернов ОО в Perl.  По счастью, Perl гибок, 
что позволяет процветать развитой ОО экосистеме.

Если вам интересно, что находится под капотом ОО в Perl, подробные детали 
описываются в L<perlobj>.


В этом руководстве подразумевается, что вы понимаете основы синтаксиса Perl, 
типы переменных, операторы и вызов подпрограмм.  Если нет, начните с 
L<perlintro>.  Необходимо также ознакомиться с L<perlsyn>, L<perlop> и 
L<perlsub>.

=head1 ОСНОВЫ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО ПОДХОДА

Большинство объектных систем разделяют ряд общих концепций. 
Возможно ранее вы слышали такие термины, как "класс", "объект", "метод", 
"атрибут". Понимание этих концепций намного облегчает чтение и написание 
объектно-ориентированного кода. Даже если вам уже хорошо знакомы эти термины, 
все же бегло просмотрите этот раздел, поскольку каждая из этих концепций 
раскрывается здесь в терминах реализации ОО в Perl.

ОО в Perl основана на классах и такой подход используется во многих ОО 
системах - в Java, C++, C#, Python, Ruby и еще куче языков. Есть и другие 
парадигмы объектно-ориентированной архитектуры.  Например, один из самых 
популярных языков программирования JavaScript использует парадигму, в основе 
которой лежат прототипы.

=head2 Объект

Любой B<объект> является структурой данных, связывающей вместе данные и
процедуры, использующие эти данные. Данные объекта называются B<атрибутами>, а
его процедуры называются B<методами>. О любом объекте можно мыслить, 
как о существительном (например, человек, web-сервис, компьютер).

Объект представляет единственную дискретную сущность. Например, объект
может представлять файл. Атрибуты файла-объекта могут включать путь,
содержимое и время последней модификации. Если мы создадим объект, 
представляющий файл F</etc/hostnames> на машине "foo.example.com", 
 то атрибут путь этого для этого объекта будет иметь значение"/etc/hostname", 
 его содержимое будет "foo\n" и время последнего изменения будет 1304974868 в секундах, прошедших с начала эпохи.

С файлом могут быть связаны методы C<rename> и C<write>.

Большинство объектов в Perl являются хешами, но ОО система рекомендует 
не полагаться на это знание. На практике лучше рассматривать внутреннюю
структуру данных объекта, как непрозрачную.

=head2 Классы

B<Класс> определяет поведение категории объектов. Класс является названием
категории (например, "File") и задает поведение объектов этой категории.

Любой объект принадлежит определенному классу. Например, объект 
F</etc/hostname> принадлежит классу F<File>. Когда мы хотим создать
определенный объект, мы обращаемся к классу и B<конструируем> или
B<создаем экземпляр> объекта. Конкретный объект часто называют B<экземпляром>
класса.

В Perl любой пакет может быть классом. Разница между пакетом, являющимся
классом, и пакетом, классом не являющимся определяется использованием пакета.
"Объявление класса" F<File>:

  package File;

В Perl нет специального ключевого слова для создания объекта. Однако,
большинство ОО модулей на CPAN используют название метода C<new> для
для конструктора нового объекта:

  my $hostname = File->new(
      path          => '/etc/hostname',
      content       => "foo\n",
      last_mod_time => 1304974868,
  );


( Не беспокойтесь о том, что делает оператор C<< -> >>, позже мы 
объясним.)

=head3 Blessing ("освящение")

Как ранее говорилось, большинство объектов в Perl являются хешами, но вообще
объект может являться любым типом данных Perl (скаляр, массив и т.д.). 
Превращение простой структуры данных в объект выполняется через B<"освящение">
этой структуры функцией B<bless>.

Хотя мы настоятельно не рекомендуем вам собирать ваши объекты с нуля,
вы должны знать термин B<bless>. Объектом является B<"блесснутая"> структура 
данных (также известная как "ссылка").  Иногда мы говорим, что объект 
"освящен в класс".

Для того, чтобы узнать название класса "освященного" объекта, используйте функцию
B<blessed> из модуля ядра Scalar::Util. Она возвращает название класса, если 
вызывается с объектом, или false в ином случае.

  use Scalar::Util 'blessed';

  print blessed($hash);      # undef
  print blessed($hostname);  # File

=head3 Конструктор

B<Конструктор> создает новый объект. Конструктор класса в Perl является
обычным методом, в этом состоит отличие от других языков программирования, 
в которых есть отдельный синтаксис для конструктора. Большинство классов в Perl
используют в качестве имени конструктора B<new>:

  my $file = File->new(...);

=head2 Методы

Как вы уже узнали, B<метод> является обычной процедурой, выполняющей операции 
с объектом. Вы можете думать о методе, как о чём то, что объект может 
B<сделать>. Если объект это существительное, то методы это глаголы (save,
print, open).

Методы в Perl это обычные процедуры, существующие в пакете класса.
Методы всегда пишутся таким образом, как если в первом аргументе они получают 
объект:

  sub print_info {
      my $self = shift;

      print "This file is at ", $self->path, "\n";
  }

  $file->print_info;
  # The file is at /etc/hostname

Особенность методов в том, I<как> они вызываются. Использование (C<< -> >>) 
сообщает Perl, что вызывается метод.

При вызове метода Perl помещает в первом аргументе B<инвокант> метода.
Странное название B<инвокант> обозначает то, что находится слева от стрелки.
Инвокантом может быть имя класса или объект. Методу можно передать
дополнительные аргументы: 

  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

=head2 Атрибуты

В любом классе могут определяться собственные B<атрибуты>. При создании
объекта мы присваиваем значения этим атрибутам. Например, у любого объекта
F<File> имеется атрибут "путь файла". Атрибуты иногда называют B<свойствами>.

В Perl нет специального синтаксиса для атрибутов.  Внутри объекта атрибуты
часто хранятся как ключи лежащего в основе объекта хеша, но не надо полагаться
на это.

Мы рекомендуем выполнять доступ к атрибутам только через B<аксессоры>. Это
методы, получающие или устанавливающие значение соответствующего
атрибута. Ранее в примере с C<print_info> мы видели вызов C<< $self->path >>.

Вам могут также встретиться термины B<getter> и B<setter>. Это две
разновидности аксессоров. Геттер возвращает значение атрибута, сеттер 
устанавливает. Другое название сеттера - B<mutator>. 

Обычно атрибуты определяются либо как только для чтения, либо для чтения и 
записи (read-only и read-write). Read-only атрибуты можно установить только 
при создании объекта, в то время, как read-write атрибуты можно изменять 
когда угодно.

Значением атрибута может являться объект. Например, вместо возврата последнего 
времени модификации в виде числа, класс С<File> может вернуть объект
L<DateTime>, представляющий это время.

Не все классы выставляют наружу изменяемые атрибуты. Также не все классы 
имеют атрибуты и методы.

=head2 Полиморфизм

B<Полиморфизм> это причудливый способ сказать, что объекты двух различных
классов разделяют одно API. Например, могут быть классы C<File> и
C<WebPage>, имеющие метод C<print_content()>. Он может производить различный 
вывод в каждом классе, но классы разделяют общий интерфейс.

Хотя два класса могут отличаться во многих аспектах, когда дело доходит 
до вызова C<print_content>, они ведут себя одинаково. Это означает, что мы 
можем попытаться вызвать C<print_content()> на объекте любого из этих классов,
и B<мы не обязаны знать, какому классу принадлежит объект!>

Полиморфизм одна из ключевых концепций объектно-ориентированной архитектуры.

=head2 Наследование

B<Наследование> позволяет создавать специализированные версии существующих
классов. Оно позволяет новым классам повторно использовать методы и атрибуты
других классов. Например, можно создать класс C<File::MP3>, B<наследующий>
от класса C<File>. Все mp3-файлы являются файлами, но не все файлы являются
mp3-файлами. 

Мы часто называем отношение наследования, как отношение B<родитель-потомок> 
или отношение B<суперкласс/подкласс>.

C<File> является B<суперклассом> класса C<File::MP3>, и C<File::MP3> является
B<подклассом> класса C<File>.

  package File::MP3;

  use parent 'File';

Модуль L<parent> предоставляет один из нескольких способов определить 
отношение наследования в Perl.

Perl допускает множественное наследование. Это значит, что класс может
наследовать от нескольких родителей. Несмотря на наличие этой возможности,  
настоятельно рекомендуем не использовать её. В обычном случае вы можете
использовать B<роли>. Они позволяют делать все, что можно делать с
множественным наследованием, но более опрятным образом.

Обратите внимание, что не является ошибкой многократно определять подклассы 
любого класса.  Это общепринято и обычно безопасно. Например, можно определить 
классы C<File::MP3::FixedBitrate> и C<File::MP3::VariableBitrate> для 
различных типов mp3 файлов.


=head2 Перегрузка и Разрешение Методов

Наследование позволяет разделять код между классами. По умолчанию, любой метод
в родительском классе доступен в дочернем классе. Дочерний класс может
явным образом B<перегрузить> метод родительского класса своей реализацией. 
Например, объект класса C<File::MP3> содержит метод C<print_info()> класса 
C<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

Процесс определения того, какой метод нужно вызвать, называется 
B<разрешением вызова метода>. Для этого Perl сначала рассматривает класс 
объекта (C<File::MP3> в данном случае). Если данный метод определен, вызывается 
версия метода этого класса. Если нет, Perl изучает каждый родительский класс 
поочередно. Класс C<File::MP3> имеет единственного родителя C<File>. Если 
нужный метод не определен в C<File::MP3>, но определен в C<File>, Perl вызовет
метод из C<File>.

Если C<File> наследует от C<DataSource>, который наследует от C<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";
  }

Часть C<SUPER::> говорит Perl искать C<print_info()> в цепочке наследования 
классов C<File::MP3>. Метод вызывается, когда найден родительский класс, 
реализующий этот метод.

Ранее мы рассказали о множественном наследовании. Его основная проблема в
значительном усложнении разрешения вызова методов.
Подробнее об этом написано в L<perlobj>.

=head2 Инкапсуляция

Идея B<инкапсуляции> в том, что объект непрозрачен.  Когда другой разработчик 
использует ваш класс, ему не надо знать, I<как> он реализован. Все, что ему 
надо знать, это I<что> делает ваш класс.

Инкапсуляция важна по нескольким причинам. Во-первых, она позволяет вам
отделить публичное API от закрытой реализации. Это значит, что вы можете
менять реализацию без боязни сломать API.

Во-вторых, хорошо инкапсулированные классы легче использовать при создании
подклассов. В идеале, подкласс использует тоже самое API для доступа к данным
объекта родительского класса. В реальном мире подклассы порой вынуждены 
нарушать инкапсуляцию, но хорошее API может минимизировать эту потребность.

Ранее мы упоминали, что большинство Perl объектов под капотом реализуется в 
виде хеша. Принципы инкапсуляции запрещают полагаться на это знание. Вместо 
этого, для доступа к данным хеша нужно использовать методы-аксессоры. Все 
объектные системы, рекомендуемые ниже, способны автоматически генерировать 
аксессоры. Никогда не потребуется выполнять доступ к объекту непосредственно 
через хеш, если вы используете одну из таких систем.

=head2 Композиция

В объектно-ориентированном коде часто можно видеть, что один объект ссылается
на другой. Это называется B<композицией>, или отношением B<has-a>.

Ранее мы говорили, что аксессор C<last_mod_time> класса C<File> может
возвращать объект C<DateTime>. Это великолепный пример композиции. Можно пойти
дальше и заставить аксессоры C<path> и C<content> также возвращать объекты. В
этом случае класс C<File> будет F<составлен> из нескольких других объектов.

=head2 Роли


B<Роли> описывают то, что класс I<делает>, в отличии от того, чем он
I<является>. Хотя роли - относительно новая сущность в Perl, они стали 
довольно популярны. Роли B<применяются> к классам. Иногда говорят, что классы
могут B<потреблять> роли.

Роли являются альтернативой наследованию для обеспечения полиморфизма.
Предположим, у нас есть два класса, C<Radio> и C<Computer>. У радио и
компьютера обычно есть переключатель вкл/выкл, и мы хотим смоделировать
этот аспект в определении наших классов.

Можно унаследовать оба класса от общего родителя, например, C<Machine>, но 
переключатели вкл/выкл имеются не у всех машин. Можно создать родительский 
класс C<HapOnOffSwitch>, но такой подход выглядит очень искусственно. У радио и
компьютера нет специализации по родителю, в реальности такой родитель выглядел
бы довольно смешным созданием. 

В этой ситуации на помощь приходят роли. Появляется смысл создать роль
C<HasOnOffSwitch> и применить ее к обеим классам.  Роль должна определять
известное API, например, методы C<turn_on()> и C<turn_off()>.

В Perl нет никаких встроенных способов описать роль. В прошлом, скрипя зубами, 
люди просто использовали множественное наследование. В настоящее
время на CPAN имеется несколько неплохих альтернатив для работы с ролями.

=head2 Когда стоит использовать ОО

Объектно-ориентированная парадигма не является наилучшим решением всех 
возможных проблем. Дамиан Конвей в своей книге I<Perl Best Practices> 
(copyright 2004, Published by O'Reilly Media, Inc.) описывает несколько
критериев, которые помогут вам понять, подходит ли ОО для решения ваших
проблем: 

=over 4

=item *

Проектируемая вами система большая, или может превратиться в большую.

=item *

Данные можно объединить в очевидные структуры, особенно если данных в каждой
структуре много.

=item *

Различные типы данных объединяются в естественную иерархию таким образом, 
что становится возможным использовать наследование и полиморфизм.

=item *

Есть данные, над которыми выполняется много различных действий.

=item *

На связанных типах данный надо выполнять одинаковые общие действия, но с
с небольшими  различиями, зависящими от типа данных.

=item *

Вы предполагаете, что потребуется добавлять новые типы данных в будущем.

=item *

Типичные взаимодействия между частями данных лучше всего представляются
операторами.

=item *

Вероятно, что реализация отдельных компонентов системы может меняться со
временем.

=item *

Система уже имеет объектно-ориентированную архитектуру.

=item *

Вашими модулями будут пользоваться многие другие программисты.

=back

=head1 ОО СИСТЕМЫ НА PERL

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

Мы настоятельно рекомендуем использовать одну из таких систем. Даже самая
минималистичная из них позволяет избежать множества рутинных действий. В
самом деле, нет хороших причин писать ваши классы с нуля.

Если вам интересны внутренности, срытые всеми этими системами, смотрите 
L<perlobj>.

=head2 Moose

L<Moose> позиционирует себя, как "постмодернистская объектная система Perl5". 
Не пугайтесь слова "постмодернизм", это всего лишь отсылка к описанию Perl, 
данному Ларри: "первый постмодернистский компьютерный язык".

L<Moose> предлагает полнофункциональную, современную ОО систему. Наибольшее 
влияние на нее оказала Common List Object System, но были также позаимствованы 
идеи из Smalltalk и некоторых других языков.  C<Moose> был создан 
Stevan Little  и в значительной степени опирается на его работу по 
проектированию ОО архитектуры Perl6.

Вот определение класса C<File> с использованием C<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";
  }

C<Moose> предлагает следующие возможности:

=over 4

=item * Декларативный сахар

Для объявления классов C<Moose> предоставляет прослойку из декларативного
"сахара". Это просто набор экспортируемых функций, с которыми объявление того,
как работает ваш класс, становится проще и приятней.

Процедура C<has()> объявляет атрибут, и C<Moose> автоматически создает
аксессор для него. Также он позаботится о создании метода C<new()>. Этот
конструктор знает об объявленных атрибутах и поэтому вы можете устанавливать
их, когда создаете новый C<File>.

=item * Встроенные роли

C<Moose> позволяет определять роли таким же образом, как и классы:

  package HasOnOfSwitch;
  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);
  }

=item * Миниатюрная система типов

В примере выше можно увидеть, как мы передаем C<< isa => 'Bool' >>
в C<has()> при создании нашего атрибута C<is_on>. Это говорит C<Moose>, что
значение этого атрибута должно иметь логический тип. При попытке установить
неверное значение в этот атрибут наша программа сгенерирует исключение.

=item * Полная интроспекция и манипуляция

Встроенные возможности интроспекции Perl крайне минимальны. C<Moose> построен
поверх них и создает целый уровень интроспекции для ваших классов. Он позволит
вам задавать вопросы типа "какие методы реализованы в классе?" Также он
позволяет изменять классы программным путем.

=item * Самодостаточность и расширяемость

C<Moose> описывает себя, используя собственный API интроспекции. Не касаясь
крутых трюков, это означает, что вы можете менять C<Moose> при помощи самого 
C<Moose>.

=item * Богатая экосистема

На CPAN существует богатая экосистема расширений C<Moose> в пространстве имен 
L<MooseX|http://search.cpan.org/search?query=MooseX&mode=dist>. В добавок,
на CPAN многие модули уже используют C<Moose>, обеспечивая вас большим
количеством примеров для изучения.

=item * Множество других возможностей

C<Moose> - это очень мощный инструмент и здесь не получится рассказать о всех
его возможностях. Мы подстрекаем вас узнать больше о C<Moose>, начать можно с
чтения L<Moose::Manual|http://search.cpan.org/perldoc?Moose::Manual>.

=back

Конечно же, C<Moose> не является совершенством.

C<Moose> может замедлить загрузку вашего кода. C<Moose> сам по себе имеет не 
маленький размер, к тому же он выполняет генерацию кода для объявления
вашего класса и этой генерации I<много>. Генерация кода означает, что во время
выполнения код работает так быстро, как может, но вы расплачиваетесь за это
при первой загрузке модуля.

Это увеличение времени загрузки может стать проблемой, если скорость запуска
приложения имеет значение. Например, в скриптах командной строки или "старых
добрых" CGI скриптах, которые загружаются при каждом запуске.

Прежде чем начать паниковать имейте ввиду, что множество людей используют 
C<Moose> при написании инструментов командной строки и другого кода,
находящегося в зависимом положении от скорости запуска.

C<Moose> также зависит от нескольких других модулей. Большинство из
них небольшие, самодостаточные модули, некоторые из них отпочковались от
самого C<Moose>. Сам C<Moose> и некоторые его зависимости требуют наличия
компилятора. Если вам нужно устанавливать ваши программы на системах без
компилятора, или наличие I<любых> зависимостей является для вас проблемой, в
этом случае C<Moose> вам не подходит.

=head2 Moo

Если вы рассматривали C<Moose> и решили, что одна из его проблем не позволяет
вам его использовать, предлагаем взглянуть на C<Moo>. C<Moo> реализует
подмножество функциональности C<Moose> в обычном пакете. Для конечного
пользователя API большинства реализуемых возможностей I<идентично> C<Moose>.
Это означает, что вы легко можете переключиться с C<Moo> на C<Moose>.

C<Moo> не реализует большинство API интроспекции C<Moose>, поэтому часто
загрузка ваших модулей происходит быстрей. В добавок, ни одна из его
зависимостей не требует XS и он может быть установлен на машины без
компилятора.

Одной из привлекательных особенностей C<Moo> является его совместимость с
C<Moose>. Когда кто то попытается использовать API интроспекции из C<Moose> в
своих классах или ролях, эти классы и роли прозрачно раздуются до классов и
ролей C<Moose>. Эта способность облегчает включение кода, использующего C<Moo>
в базирующийся на C<Moose> код, и наоборот. 

Например, C<Moose> класс может стать подклассом C<Moo> класса с помощью
C<extend>, или использовать роль C<Moo> с помощью C<with>.

Авторы C<Moose> надеются, что однажды C<Moo> станет не нужным, когда C<Moose>
достаточно улучшится, но сейчас C<Moo> является достойной альтернативой.

=head2 Class::Accessor

L<Class::Accessor> является полярной противоположностью C<Moose>. Он
предоставляет очень немного возможностей и не является самодостаточным.

Однако, он очень прост, написан на читом Perl и зависит только от модулей
ядра. Также он предлагает "Moose-подобный" API для поддерживаемых им
возможностей, подключаемый по запросу.

Хотя даже он и делает не так много, предпочтительней писать ваши
классы с его помощью, а не с нуля.

Вот наш класс C<File> с использованием C<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";
  }

Флаг импорта C<antlers> указывает C<Class::Accessor>, что вы хотите определять
атрибуты, используя C<Moose>-подобный синтаксис. C<is> единственный параметр,
который можно передать в C<has>. Если вы решите использовать
C<Class::Accessor>, рекомендуем вам пользоваться Moose-подобным синтаксисов,
потому что будут легче переключиться на C<Moose>, если возникнет такое 
желание.

Подобно C<Moose>, C<Class::Accessor> генерирует аксессоры и конструктор для
вашего класса.

=head2 Class::Tiny

Наконец, у нас есть L<Class::Tiny>. Этот модуль полностью соответствует своему
имени. Он невероятно мал и не зависит абсолютно ни от чего, кроме Perl. 
Однако, мы все еще считаем, что много легче использовать его, чем писать ваш
ОО код с нуля.

В очередной раз наш C<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";
  }

Всё!

С C<Class::Tiny> все аксессоры будут иметь тип read-write. Он также генерирует
аксессоры и конструктор.

Для использования C<Moose>-подобного синтаксиса есть L<Class::Tiny::Antlers>.

=head2 Role::Tiny

Как описывалось выше, роли предоставляют альтернативу наследованию, но в Perl
нет никакой встроенной поддержки ролей. Если ваш выбор пал на Moose, вы
получите заодно полноценную реализация ролей. Однако, если вы выбрали один из
других рекомендуемых ОО модулей, вам можете использовать роли из
C<Role::Tiny>.  

C<Role::Tiny> обеспечивает почти те же возможности, что и система ролей
C<Moose>, но в намного меньшем пакете. Более значимо, что он не поддерживает
ни в каком виде объявление атрибутов, так что придется делать это вручную. 
Все же, он полезен, и хорошо работает с связке с C<Class::Accessor> и
C<Class::Tiny>.

=head2 Резюме по ОО системам

Краткий повтор рассмотренных вариантов:

=over 4

=item * L<Moose>

C<Moose> имеет наибольшее число опций. В нем много возможностей, богатая
экосистема и процветающее сообщество пользователей. Также мы кратко 
рассмотрели C<Moo>, он представляет собой облегченную версию C<Moose> и 
является разумной альтернативой, если Moose не подходит по каким то причинам.

=item * L<Class::Accessor>

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

=item * L<Class::Tiny>

C<Class::Tiny> поддерживает абсолютный минимум опций. Не имеет зависимостей,
почти не имеет синтаксиса, требующего изучения. Хороший вариант для
супер-минимальной рабочей среды и быстрого наброска чего либо не беспокоясь о
деталях.

=item * L<Role::Tiny>

Используйте C<Role::Tiny> вместе с C<Class::Accessor> или C<Class::Tiny>, 
если вы начали рассматривать множественное наследование. Если вы дорастете до
использования C<Moose>, то в нем есть собственная реализация ролей.

=back

=head2 Другие ОО системы

Кроме рассмотренных здесь, на CPAN можно найти буквально дюжины ОО модулей и
вы, вероятно, запускали один или более из них, если работали с чужим кодом.
Кроме того, в дикой природе чрезвычайно много кода, который выполняет всю 
работу  ОО "своими руками". Если вам необходимо поддерживать такой код,
читайте L<perlobj> для понимания, как работает Perl ОО изнутри.

=head1 ЗАКЛЮЧЕНИЕ

Как говорилось, минималистичная система Perl ОО привела к появлению систем ОО
на CPAN. Хотя вы все еще можете жить в каменном веке и кодировать ваши классы
вручную, нет реальных причин делать так в современном Perl.

Для небольших систем об основных шаблонных действиях позаботятся
L<Class::Tiny> или L<Class::Accessor>.

Для больших проектов богатый набор возможностей предоставит L<Moose>, что
позволит вам фокусироваться на написании бизнес-логики.

Мы предлагаем вам поиграться с L<Moose>, L<Class::Accessor> и L<Class::Tiny> и
сделать выбор, подходящий именно вам.

=cut

=head1 ПЕРЕВОДЧИКИ
 
=over
 
=item * Андрей Асякин C<< <asan999 at gmail.com> >>
 
=item * Николай Мишин C<< <mi at ya.ru> >>

=back