Объектно-ориентированное программирование в Perl появилось не сразу — изначально язык был процедурным. ООП было добавлено путем внедрения динамических структур на базе хэшей и пакетов. Perl не использует встроенного ключевого слова class, как в большинстве других языков, а оперирует пакетами и блессингом ссылок.
Первая версия Perl ООП — это просто пакет, экспортирующий функции, и структура данных (обычно хэш), на которую через функцию bless навешивается принадлежность к пакету. Позднее появились CPAN-модули типа Moose/Mouse/Moo, реализующие полнофункциональный мета-ООП (метаклассы, атрибуты, роли).
Отсутствие единого паттерна ООП ведёт к разнообразию стилей и несовместимости ООП-кода между проектами. Ошибки возможны из-за динамической природы языка (ошибки в именах, ранний/поздний binding, манипуляции методом bless вручную).
Пример кода:
package Animal; sub new { my ($class, %args) = @_; bless { %args }, $class; } sub speak { my $self = shift; print "Животное говорит "; } package Cat; our @ISA = ('Animal'); sub speak { my $self = shift; print "Кот мяукает "; } my $cat = Cat->new(name => 'Barsik'); $cat->speak; # Кот мяукает
Ключевые особенности:
Что происходит, если в new возвращать не bless'ed ссылку, а просто хэш?
Возврат не-bless'нутой ссылки приводит к тому, что дальнейшие вызовы методов через->$obj потеряют связь с пакетом и не найдут нужный метод — произойдет фатальная ошибка.
Как Perl реализует множественное наследование и разрешение конфликтов методов?
Perl разрешает множественное наследование — в массиве @ISA может быть несколько пакетов. Поиск метода идёт глубиной в ширину, слева направо, по всем родителям. При конфликте будет взят первый найденный метод.
Можно ли в Perl "переблессить" (re-bless) объект во время выполнения, и что это означает?
Да, через bless можно изменить принадлежность объекта к другому пакету во время исполнения. Это можно использовать для изменения "типа" объекта. Однако есть риск несоответствия внутреннего содержания объекта новым методам.
Пример:
bless $cat, 'Dog'; # Теперь $cat ведет себя как собака!
В проекте создают объекты через bless очевидно неинициализированного массива, а методы ожидают ссылку на хэш. Программа падает при вызове любого метода, хотя синтаксис Perl позволяет сделать bless над что угодно.
Плюсы:
Минусы:
Использование Moose и валидируемых конструкторов, строгая типизация атрибутов, автоматическое создание методов доступа, лаконичное описание связей между объектами.
Плюсы:
Минусы: