Может кто-то говорить мне, почему основное не находит методы сгенерированными Классом:: Средство доступа в этом очень небольшом и тривиальном примере?
Эти немного строк кода перестали работать с
perl codesnippets/accessor.pl
Can't locate object method "color" via package "Critter" at
codesnippets/accessor.pl line 6.
см. код:
#!/opt/local/bin/perl
# The whole Class::Accessor thing does not work !!
my $a = Critter->new;
$a->color("blue");
$a->display;
exit 0;
package Critter;
use base qw(Class::Accessor );
Critter->mk_accessors ("color" );
sub display {
my $self = shift;
print "i am a $self->color " . ref($self) . ", whatever this word means\n";
}
FM дает вам хороший совет. mk_accessors
необходимо запустить раньше другого кода. Кроме того, обычно вы помещаете Critter
в отдельный файл, а используете Critter
для загрузки модуля.
Это работает, потому что использование
имеет эффекты времени компиляции. Выполнение use Critter;
аналогично выполнению BEGIN {require Critter; Critter-> импорт; }
Это гарантирует, что код инициализации вашего модуля будет запущен до того, как остальная часть кода даже скомпилируется.
Допускается помещать несколько пакетов в один файл. Часто я создаю прототипы связанных объектов в одном файле, так как он сохраняет все под рукой, пока я создаю прототип. Когда придет время, также довольно легко разделить файл на отдельные части.
Из-за этого я считаю, что лучший способ хранить несколько пакетов в одном файле и работать с ними так, как если бы я их использовал, - это поместить определения пакетов в блоки BEGIN
, заканчивающиеся на истинное значение. Используя мой подход, ваш пример был бы записан:
#!/opt/local/bin/perl
my $a = Critter->new;
$a->color("blue");
$a->display;
BEGIN {
package Critter;
use base qw(Class::Accessor );
use strict;
use warnings;
Critter->mk_accessors ("color" );
sub display {
my $self = shift;
# Your print was incorrect - one way:
printf "i am a %s %s whatever this word means\n", $self->color, ref $self;
# another:
print "i am a ", $self->color, ref $self, "whatever this word means\n";
}
1;
}
Я просто хотел предложить вам лучшее решение - не стесняйтесь проголосовать за это, если решение не понравится, но C::A - действительно плохая идея в наше время, используйте Moose:
package Critter;
use Moose;
has 'color' => ( isa => 'Str', is => 'rw' ); # Notice, this is typed
sub display {
my $self = shift;
printf (
"i am a %s %s whatever this word means\n"
, $self->color
, $self->meta->name
);
}
package main;
use strict;
use warnings;
my $c = Critter->new; # or my $c = Critter->new({ color => blue });
$c->color("blue");
$c->display;
Ваш код не работает. Если вы хотите, чтобы аксессор color
был доступен, вам нужно вызвать mk_accessors
до того, как вы создадите свой объект и начнете с ним что-то делать. Например:
package Critter;
use base qw(Class::Accessor);
Critter->mk_accessors("color");
sub display {
my $self = shift;
print $self->color, ' ', ref($self), "\n";
}
package main;
my $c = Critter->new;
$c->color("blue");
$c->display;
Чаще всего код Critter
находится в собственном модуле (Critter.pm
), и вся магия mk_accessor
происходит, когда ваш основной сценарий запускает use Critter
- задолго до того, как ваш сценарий начинает работать с объектами Critter
и Varmint
.