在Moose :: Role中访问MooseX :: ClassAttribute

时间:2012-05-24 03:29:34

标签: perl moose

这是难题。我使用Moose :: Role作为接口,具体类必须实现角色定义的必需属性构建器。该角色还定义了一些在属性上执行逻辑的方法。这是我正在努力做的精简版。

package Parent;
use Moose::Role;
requires '_build_permission_level';

has 'permission_level' => (
    is => 'ro',
    isa => Int,
    lazy_build => 1,
);

use constant {
    LEVEL1 = 1,
    LEVEL2 = 2,
    LEVEL3 = 3,
};

sub can_do_action {
    my $self = shift;
    return $self->permission_level() >= LEVEL2;
}

package Child;
use Moose;
with 'Parent';

sub _build_permission_level { return Parent->LEVEL3; }

显然我有很多子类,具有不同的权限级别。现在这个工作,除了它非常低效。所有子实例将始终具有相同的权限级别,但我必须实例化它才能询问它是否可以执行操作。批量运行10,000次时,你可以得到图片。

相反,我想让permission_level成为一个class属性。以Moose-y的方式解决效率问题。请注意permission_level如何不再需要$ self。

package Parent;
use Moose::Role;
use MooseX::ClassAttribute;
requires '_build_permission_level';

class_has 'permission_level' => (
    is => 'ro',
    isa => Int,
    builder => '_build_permission_level',
);

use constant {
    LEVEL1 = 1,
    LEVEL2 = 2,
    LEVEL3 = 3,
};

sub can_do_action {
    return permission_level() >= LEVEL2;
}

package Child;
use Moose;
with 'Parent';

sub _build_permission_level { return Parent->LEVEL3; }

这死于一个未定义的子程序错误,找不到Parent :: permission_level。所以父母不知道permission_level。真?我很困惑它无法访问自己的类属性。我必须遗漏一些非常简单的东西。但更基本的是,我应该如何让Parent为Child提供的类属性提供逻辑?

1 个答案:

答案 0 :(得分:2)

错误表明在编译时不存在子Parent::permission_level。这是真的:hasclass_has是运行时构造;当编译can_do_action中的呼叫时,尚未创建子。

真正的问题是你使用错误的语法来调用类方法。因此重写can_do_action

sub can_do_action {
    my ($class) = @_;

    return $class->permission_level >= LEVEL2;
}

它应该可以正常工作。与普通函数调用不同,方法调用直到运行时才会得到解决,此时将存在Parent::permission_level