在继承函数中访问类变量?

时间:2014-04-10 14:51:36

标签: perl inheritance

我正在尝试在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)?导出所有方法而不是继承,我听说不应该这样做(污染命名空间,这里不是问题)?

  • 这仍然是使用对象和对象的问题 属性/变量?由于我的团队,我试图避免它 厌恶面向对象。

  • 这是继承通常如何工作, 还是只是Perl?我认为该方法将在范围内调用 子类的,不传递给父类。

1 个答案:

答案 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');语法覆盖。