Мне кажется, что вы близки к переизобретению Лося плохо. Попробуйте использовать Moose вместо создания чего-то похожего, но менее полезного.
Сообщение об ошибке означает, что вы передаете строку в месте, где ваш код ожидает ссылку на код. Получите трассировку стека, чтобы выяснить, откуда исходит ошибка.
Вы можете сделать это, используя Carp :: Always, переопределив обработчик $SIG{__DIE__}
для генерации трассировки стека, или вставив Carp::confess
в ваш код.
Вот решение sigdie, вставьте его в свой код, где оно будет выполняться до инициализации вашего модуля:
$SIG{__DIE__} = sub { Carp::confess(@_) };
Возможно, вам понадобится поместить его в блок BEGIN
.
Я бы очень хотел отговорить вас от такого подхода к строительству объектов. Вы счастливо благословляете любую случайную чушь, передаваемую конструктору как часть вашего объекта! Вы беспечно проникаете в свои внутренние объекты. Правила проверки полей * do not принадлежат конструктору - они принадлежат мутаторам атрибута.
Если вы должны использовать самодельный объект, очистите свои практики:
# Here's a bunch of validators.
# I set them up so that each attribute supports:
# Multiple validators per attribute
# Distinct error message per attribute
my %VALIDATORS = (
some_attribute => [
[ sub { 'foo1' }, 'Foo 1 is bad thing' ],
[ sub { 'foo2' }, 'Foo 2 is bad thing' ],
[ sub { 'foo3' }, 'Foo 3 is bad thing' ],
],
other_attribute => [ [ sub { 'bar' }, 'Bar is bad thing' ] ],
);
sub new {
my $class = shift; # Get the invocant
my %args = @_; # Get named arguments
# Do NOT make this a clone method as well
my $self = {};
bless $class, $self;
# Initialize the object;
for my $arg ( keys %args ) {
# Make sure we have a sane error message on a bad argument.
croak "Bogus argument $arg not allowed in $class\n"
unless $class->can( $arg );
$self->$arg( $args{$arg} );
}
return $self;
}
# Here's an example getter/setter method combined in one.
# You may prefer to separate get and set behavior.
sub some_attribute {
my $self = shift;
if( @_ ){
my $val = shift;
# Do any validation for the field
$_->[0]->($val) or croak $_->[1]
for @{ $VALIDATORS{some_attribute} || [] };
$self->{some_attribute} = $val;
}
return $self->{some_attribute};
}
Весь этот код очень хорош, но вы должны повторять свой код атрибута для каждого атрибута. Это означает много ошибочных шаблонов кода. Вы можете обойти эту проблему, научившись использовать замыкания или строковые значения eval для динамического создания ваших методов, или вы можете использовать одну из многих библиотек Perl для генерации классов, таких как Class :: Accessor, Class :: Struct, Accessor :: Tiny и так далее. .
Или вы можете выучить [Лося] [3]. Moose - это новая (ish) объектная библиотека, которая переняла практику Perl OOP. Он предоставляет мощный набор функций и значительно сокращает количество шаблонов по сравнению с классическим ООП Perl:
use Moose;
type 'Foo'
=> as 'Int'
=> where {
$_ > 23 and $_ < 42
}
=> message 'Monkeys flew out my butt';
has 'some_attribute' => (
is => 'rw',
isa => 'Foo',
);