我正在尝试在Perl中创建从单个父级继承类函数的子类。我让它部分工作,使用对象方法语法Child->inheritedMethod()
来调用子进程外的继承函数,并在子类中调用my $class=shift; $class->inheritedMethod();
,如here所述。
但是,对于继承的方法,似乎控制权传递给父类,并且该方法在父作用域中使用父变量运行。例如,这是在Parent类中:
our $VERSION = 0.11;
our $NICKNAME = "Parent Base";
sub version{ $VERSION }
sub whoami{ $NICKNAME }
sub whereami{
my $class = shift;
print "should be printing whereami right now...\n";
print "## In ",(caller(1))[3]," of ",$class->whoami," ",$class->version," in ",__PACKAGE__,"\n";
}
每个子类都声明自己的$VERSION
和$NICKNAME
,我希望可以使用它来代替父变量。但是,当我从孩子那里打电话给whereami
时,它会给出
## Child::Method of Parent Base 0.11 in Parent
。
问题:
有解决方法吗?我应该使用的其他模块如Moo(se)?导出所有方法而不是继承,我听说不应该这样做(污染命名空间,这里不是问题)?
这仍然是使用对象和对象的问题 属性/变量?由于我的团队,我试图避免它 厌恶面向对象。
答案 0 :(得分:4)
问题是该方法从声明它的词法范围(即父类)访问变量。因此,类变量与类属性不同。
您可以通过完全限定其名称来访问正确的变量(strict refs
下无法使用
#!/usr/bin/perl
use warnings;
use strict;
{ package Parent;
our $package = 'Parent';
sub get_package {
my $class = shift;
{ no strict 'refs';
return (caller(0))[3], $class, ${"$class\::package"}
}
}
}
{ package Son;
use parent 'Parent';
our $package = 'Son';
}
print join ' ', 'Son'->get_package, "\n";
print join ' ', 'Parent'->get_package, "\n";
在Moo *中,您可以使用Moo*X::ClassAttribute
:
#!/usr/bin/perl
use warnings;
use strict;
{ package Parent;
use Moo;
use MooX::ClassAttribute;
class_has package => (is => 'ro',
default => 'Parent');
sub get_package {
my $class = shift;
return $class->package;
}
}
{ package Son;
use Moo;
use MooX::ClassAttribute;
extends 'Parent';
class_has package => (is => 'ro',
default => 'Son');
}
print 'Parent'->get_package, "\n";
print 'Son'->get_package, "\n";
请注意,MooX :: ClassAttribute说
尚不支持在子类中覆盖类属性及其访问器。
与Moose不同,您无法使用class_has '+package' => (default => 'Son');
语法覆盖。