Perl Class :: Accessor失败,简单的例子 - 为什么?

Ale*_*x F 5 perl cpan

有人能告诉我为什么main在这个非常小而简单的例子中找不到Class :: Accessor生成的方法吗?

这几行代码失败了

perl codesnippets/accessor.pl
Can't locate object method "color" via package "Critter" at
codesnippets/accessor.pl line 6.
Run Code Online (Sandbox Code Playgroud)

看代码:

#!/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";
    }
Run Code Online (Sandbox Code Playgroud)

FMc*_*FMc 8

您的代码无序.如果您希望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;
Run Code Online (Sandbox Code Playgroud)

更常见的是,Critter代码将在其自己的module(Critter.pm)中,并且mk_accessor当您的主脚本运行时use Critter- 在脚本开始使用CritterVarmint对象之前 - 会发生所有魔法.


dao*_*oad 3

FM给你很好的建议。 mk_accessors需要在其他代码之前运行。另外,通常您会放入Critter一个单独的文件并use Critter加载模块。

这是有效的,因为use有编译时间的影响。执行use Critter;与执行相同BEGIN { require Critter; Critter->import; }这可以保证模块的初始化代码将在其余代码编译之前运行。

将多个包放在一个文件中是可以接受的。通常,我会将相关对象的原型放在一个文件中,因为它可以在我进行原型设计时使所有内容都方便。当需要时,将文件分成单独的部分也很容易。

因此,我发现将多个包保留在一个文件中并像使用它们一样使用它们的最佳方法是将包定义放在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;
}
Run Code Online (Sandbox Code Playgroud)