【问题标题】:Writing a builder for a MooseX::ClassAttribute in a Moose::Role在 Moose::Role 中为 MooseX::ClassAttribute 编写构建器
【发布时间】:2016-01-19 23:05:43
【问题描述】:

我想定义一个具有类属性和构建器的角色。无论我尝试过什么,这都失败了。我找到了两种解决方法:

  1. 不使用类属性,而是使用普通属性。在我的情况下这是有问题的,因为我想在我的真实代码中修改属性(对于所有实例)。
  2. 将构建器放入类中(而不是放入角色中)。这也是有问题的,因为这意味着修改所有使用此角色的类。

这是一个最小的例子:

package MyRole;
use Moose::Role;
use MooseX::ClassAttribute;

sub _build_value {
    return "in MyRole";
}

class_has 'value' => (
    is => 'ro',
    isa => 'Str',
    builder => '_build_value',
);

1;

package Appli;
use Moose;

with 'MyRole';

1;

package main;

my $e=Appli->new();

print $e->value, "\n";

结果:

$ perl ./test.pl 
Appli does not support builder method '_build_value' for attribute 'value' at /usr/share/perl5/MooseX/ClassAttribute/Trait/Attribute.pm line 81.
Class::MOP::Class:::around(CODE(0x13d6c78), Moose::Meta::Class::__ANON__::SERIAL::11=HASH(0x1982460), "Appli") called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Class/MOP/Method/Wrapped.pm line 164
Moose::Meta::Class::__ANON__::SERIAL::11::_wrapped__call_builder(Moose::Meta::Class::__ANON__::SERIAL::11=HASH(0x1982460), "Appli") called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Class/MOP/Method/Wrapped.pm line 95
Moose::Meta::Class::__ANON__::SERIAL::11::_call_builder(Moose::Meta::Class::__ANON__::SERIAL::11=HASH(0x1982460), "Appli") called at /usr/share/perl5/MooseX/ClassAttribute/Trait/Attribute.pm line 54
MooseX::ClassAttribute::Trait::Attribute::_initialize(Moose::Meta::Class::__ANON__::SERIAL::11=HASH(0x1982460), Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0)) called at /usr/share/perl5/MooseX/ClassAttribute/Trait/Attribute.pm line 32
Class::MOP::Class:::after(Moose::Meta::Class::__ANON__::SERIAL::11=HASH(0x1982460), Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0)) called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Class/MOP/Method/Wrapped.pm line 57
Moose::Meta::Class::__ANON__::SERIAL::11::_wrapped_attach_to_class(Moose::Meta::Class::__ANON__::SERIAL::11=HASH(0x1982460), Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0)) called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Class/MOP/Method/Wrapped.pm line 95
Moose::Meta::Class::__ANON__::SERIAL::11::attach_to_class(Moose::Meta::Class::__ANON__::SERIAL::11=HASH(0x1982460), Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0)) called at /usr/share/perl5/MooseX/ClassAttribute/Trait/Class.pm line 66
MooseX::ClassAttribute::Trait::Class::_attach_class_attribute(Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0), Moose::Meta::Class::__ANON__::SERIAL::11=HASH(0x1982460)) called at /usr/share/perl5/MooseX/ClassAttribute/Trait/Mixin/HasClassAttributes.pm line 40
MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes::add_class_attribute(Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0), Moose::Meta::Class::__ANON__::SERIAL::11=HASH(0x1982460)) called at /usr/share/perl5/MooseX/ClassAttribute/Trait/Class.pm line 41
Class::MOP::Class:::around(CODE(0x17fae38), Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0), Moose::Meta::Class::__ANON__::SERIAL::11=HASH(0x1982460)) called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Class/MOP/Method/Wrapped.pm line 164
Moose::Meta::Class::__ANON__::SERIAL::10::_wrapped_add_class_attribute(Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0), Moose::Meta::Class::__ANON__::SERIAL::11=HASH(0x1982460)) called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Class/MOP/Method/Wrapped.pm line 95
Moose::Meta::Class::__ANON__::SERIAL::10::add_class_attribute(Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0), Moose::Meta::Class::__ANON__::SERIAL::11=HASH(0x1982460)) called at /usr/share/perl5/MooseX/ClassAttribute/Trait/Application/ToClass.pm line 44
MooseX::ClassAttribute::Trait::Application::ToClass::_apply_class_attributes(Moose::Meta::Class::__ANON__::SERIAL::8=HASH(0x1a29940), Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x1a27298), Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0)) called at /usr/share/perl5/MooseX/ClassAttribute/Trait/Application.pm line 13
Class::MOP::Class:::after(Moose::Meta::Class::__ANON__::SERIAL::8=HASH(0x1a29940), Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x1a27298), Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0)) called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Class/MOP/Method/Wrapped.pm line 57
Moose::Meta::Class::__ANON__::SERIAL::8::_wrapped_apply_attributes(Moose::Meta::Class::__ANON__::SERIAL::8=HASH(0x1a29940), Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x1a27298), Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0)) called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Class/MOP/Method/Wrapped.pm line 95
Moose::Meta::Class::__ANON__::SERIAL::8::apply_attributes(Moose::Meta::Class::__ANON__::SERIAL::8=HASH(0x1a29940), Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x1a27298), Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0)) called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Moose/Meta/Role/Application.pm line 59
Moose::Meta::Role::Application::apply(Moose::Meta::Class::__ANON__::SERIAL::8=HASH(0x1a29940), Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x1a27298), Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0)) called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Moose/Meta/Role/Application/ToClass.pm line 31
Moose::Meta::Role::Application::ToClass::apply(Moose::Meta::Class::__ANON__::SERIAL::8=HASH(0x1a29940), Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x1a27298), Moose::Meta::Class::__ANON__::SERIAL::10=HASH(0x19683d0)) called at /usr/share/perl5/MooseX/ClassAttribute/Trait/Application/ToClass.pm line 27
Class::MOP::Class:::around(CODE(0x14ae360), Moose::Meta::Class::__ANON__::SERIAL::8=HASH(0x1a29940), Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x1a27298), Moose::Meta::Class=HASH(0x175d658), HASH(0x1a22b28)) called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Class/MOP/Method/Wrapped.pm line 164
Moose::Meta::Class::__ANON__::SERIAL::8::_wrapped_apply(Moose::Meta::Class::__ANON__::SERIAL::8=HASH(0x1a29940), Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x1a27298), Moose::Meta::Class=HASH(0x175d658), HASH(0x1a22b28)) called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Class/MOP/Method/Wrapped.pm line 95
Moose::Meta::Class::__ANON__::SERIAL::8::apply(Moose::Meta::Class::__ANON__::SERIAL::8=HASH(0x1a29940), Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x1a27298), Moose::Meta::Class=HASH(0x175d658), HASH(0x1a22b28)) called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Moose/Meta/Role.pm line 472
Moose::Meta::Role::apply(Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x1a27298), Moose::Meta::Class=HASH(0x175d658)) called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Moose/Util.pm line 172
Moose::Util::_apply_all_roles(Moose::Meta::Class=HASH(0x175d658), undef, "MyRole") called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Moose/Util.pm line 114
Moose::Util::apply_all_roles(Moose::Meta::Class=HASH(0x175d658), "MyRole") called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Moose.pm line 59
Moose::with(Moose::Meta::Class=HASH(0x175d658), "MyRole") called at /usr/lib/x86_64-linux-gnu/perl5/5.22/Moose/Exporter.pm line 419
Moose::with("MyRole") called at ./test.pl line 20

更新:我通过添加“lazy => 1”来解决它。然后它完美地工作。如果没有“lazy”,则可能会在角色完全导入之前调用构建器。

【问题讨论】:

    标签: perl moose


    【解决方案1】:

    您在这种情况下使用lazy 与其说是一种解决方法,不如说是正确的解决方案。 MooseX::ClassAttribute 实现为 Moose::Role。在MyRole 完全组合成Appli 之前,Perl 调用class_has,它尝试调用_build_value 作为Appli 类的方法。由于该方法尚未组合成AppliMooseX::ClassAttribute 因上述错误而死。使用lazy 会推迟对_build_value 的评估,直到MyRole 完全组合成Appli

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-04
      • 1970-01-01
      • 1970-01-01
      • 2013-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多