Perl — динамический язык, поддерживающий прототипное ООП на базе хэшей и пакетов. Для создания объекта обычно используется bless:
package Animal; sub new { my ($class, %args) = @_; return bless { %args }, $class; } sub speak { print "An animal makes a sound "; } package Dog; use parent 'Animal'; # или our @ISA = ('Animal') sub speak { print "Woof! "; } my $dog = Dog->new(name => 'Rex'); $dog->speak; # Выведет: Woof!
Здесь конструктор new создает хэш с данными объекта и связывает его с классом. Методы объявляются как обычные подпрограммы. Наследование возможно через @ISA или модуль parent/base. ООП в Perl гибкое, но не строгое, что открывает и дополнительные возможности, и тонкости.
Как лучше реализовать приватные свойства/методы объекта в Perl, учитывая отсутствие синтаксиса private/protected?
Ответ: Нет встроенного механизма, однако приватность достигается через лексические переменные вне пакета или соглашения о нейминге (_private). Например:
package Car; my $secret = 'hidden'; # приватно для пакета sub _private { ... } # соглашение: не вызывать извне
Такой подход не защищает от доступа, но считается стандартом.
История
На проекте был определён объект, содержащий массив ссылок на другие объекты. Разработчики забывали вызывать методы как $obj->method, вызывая их как method($obj), что приводило к неожиданным результатам, особенно при наследовании и переопределении методов – неверно определялся класс, и вызывались родительские методы вместо дочерних.
История
Использование переменной-пакета вместо лексической переменной для хранения состояния объекта приводило к тому, что одно изменение состояния отражалось у всех экземпляров класса, т.к. данные были общими, а не индивидуальными для объекта.
История
Неявная работа с переменной @ISA для наследования, при динамической подгрузке классов, в больших проектах приводила к тому, что списки родителей не обновлялись вовремя, и программа неожиданно теряла методы или получала неверную иерархию.