有人可以告诉我为什么main在这个非常小而简单的例子中找不到Class :: Accessor生成的方法吗?
这几行代码以
失败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";
}
答案 0 :(得分: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;
更常见的是,Critter
代码将位于自己的模块中(Critter.pm
),并且当您的主脚本运行mk_accessor
时,所有use Critter
魔法都会发生 - - 在您的脚本开始使用Critter
和Varmint
个对象之前。
答案 1 :(得分:3)
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;
}
答案 2 :(得分:2)
我只是想为你提供一个更好的解决方案 - 如果解决方案不受欢迎,请随意将其遗忘,但C :: A在这个时代真的是一个坏主意,使用{{3} }:
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;