3

これが難問です。私はインターフェースとして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をクラス属性にします。Moose-yの方法で効率の問題を解決します。permit_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の知識を持っていません。本当に?独自のクラス属性にアクセスできない方法がわかりません。本当にシンプルなものが欠けているに違いありません。しかし、さらに基本的には、Childが提供するクラス属性のロジックをParentに提供させるにはどうすればよいでしょうか。

4

1 に答える 1

2

エラーが示すのは、コンパイル時にサブが存在しないことParent::permission_levelです。そして、これは真実です。 hasそしてclass_has、実行時の構成です。can_do_action呼び出しがコンパイルされるとき、サブはまだ作成されていません。

本当の問題は、クラスメソッドを呼び出すために間違った構文を使用していることです。このように書き直しcan_do_actionてください:

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

    return $class->permission_level >= LEVEL2;
}

正常に動作するはずです。プレーンな関数呼び出しとは異なり、メソッドの呼び出しは実行時まで解決されません。実行時はその時点でParent::permission_level存在します。

于 2012-05-24T07:15:33.757 に答える