Основываясь на предыдущем запросе относительно Class :: Struct vs Object :: Accessor, я хотел бы найти лучший способ назначения подпрограммных подпрограмм из coderefs в конструкторах объектов.Эй, у меня есть атрибуты OO, поэтому давайте перейдем к методам:)
Обратите внимание, что я сказал «лучший» способ.Я уже нашел два способа сделать это, которые также кажутся популярными ответами на подобные вопросы, но они требуют обхода строгих правил и предупреждений соответственно.
Обратите внимание, что этот пример дает классному пользователю возможность переопределитьметод форматирования при строительстве.Плохой пример, но вы поняли.Чтобы превентивно опровергнуть OO-пуристы, в моем конкретном проекте это имеет больше смысла, чем когда класс-пользователь подклассирует его своей собственной переопределенной версией.
Вот две мои попытки:* А другой:
use 5.014;
use autodie;
use strict;
use warnings;
package Account {
use base 'Object::Accessor';
sub new {
my ($type, %args) = @_;
my $self = bless { }, $type;
$self->mk_accessors(qw(
first_name last_name age_in_years activated
));
$self->first_name( $args{first_name } // 'Default First Name' );
$self->last_name( $args{last_name } // 'Default Last Name' );
$self->age_in_years($args{age_in_years} // 'Default Age in Years');
$self->activated( $args{activated } // 'Default Activated' );
{
# Stop skim reading and look here!
no strict 'refs';
*{'formatted'} = $args{formatted} || sub {
return 'Default formatting routine';
};
}
return $self;
}
}
my $account = Account->new;
say $account->formatted;
# Output: Default formatting routine
Первый подход должен работать без предупреждений, но это не так, потому что Perl думает, что я его нигде не использую, и помечает его какпредупреждение во время выполнения.Последний не работает без обхода строгих правил, и так оно и должно быть:)
Все, что я делаю, это присваиваю метод коду, предоставленному пользователем.Это должен быть простой способ сделать это.
Обратите внимание, что определение новой подпрограммы, которая вызывает определяемый пользователем coderef, также не работает, так как из него нельзя получить доступ к лексическим% args.
В то время как наши присваивают переменные пакета, он не может выполнять переходы.
Воздержание от выхода из сада строгих правил и предупреждений, каков самый чистый способ сделать это?Черт, возможно, есть способ сделать это, используя модуль Object :: Accessor, о котором я просто не знаю.