Класс Perl:: отказ Средства доступа, тривиальный пример - почему?

Может кто-то говорить мне, почему основное не находит методы сгенерированными Классом:: Средство доступа в этом очень небольшом и тривиальном примере?

Эти немного строк кода перестали работать с

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";
    }
5
задан Alex F 4 June 2010 в 11:13
поделиться

3 ответа

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;
}
3
ответ дан 18 December 2019 в 14:42
поделиться

Я просто хотел предложить вам лучшее решение - не стесняйтесь проголосовать за это, если решение не понравится, но 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;
2
ответ дан 18 December 2019 в 14:42
поделиться

Ваш код не работает. Если вы хотите, чтобы аксессор 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.

8
ответ дан 18 December 2019 в 14:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: