在MooseX :: Declare中创建BUILD方法的正确方法是什么?

时间:2022-08-24 22:17:17

I am having difficulty with the BUILD method in MooseX::Declare. If I say:

我在MooseX :: Declare中使用BUILD方法有困难。如果我说:

#!/usr/bin/perl

use MooseX::Declare;

class Foo {
    has foo => (is => "rw", isa => "Str", default => "foo");

    method BUILD {
        print "I was called\n";
    }
}

Foo->new;

I get the following less than helpful error message:

我得到以下不是有用的错误消息:

Reference found where even-sized list expected at /Users/cowens/perl5/lib/perl5/MooseX/Method/Signatures/Meta/Method.pm line 335.
Validation failed for 'MooseX::Types::Structured::Tuple[MooseX::Types::Structured::Tuple[Object],MooseX::Types::Structured::Dict[]]' failed with value [ [ Foo=HASH(0x804b20) ], { HASH(0x8049e0) => undef } ], Internal Validation Error is: Validation failed for 'MooseX::Types::Structured::Dict[]' failed with value { HASH(0x8049e0) => undef } at /Users/cowens/perl5/lib/perl5/MooseX/Method/Signatures/Meta/Method.pm line 365
        MooseX::Method::Signatures::Meta::Method::validate('MooseX::Method::Signatures::Meta::Method=HASH(0xb8aab0)', 'ARRAY(0xb8ab30)') called at /Users/cowens/perl5/lib/perl5/MooseX/Method/Signatures/Meta/Method.pm line 139
        Foo::BUILD('Foo=HASH(0x804b20)', 'HASH(0x8049e0)') called at generated method (unknown origin) line 25
        Foo::new('Foo') called at test.pl line 13

But if I say:

但如果我说:

#!/usr/bin/perl

use MooseX::Declare;

class Foo {
    has foo => (is => "rw", isa => "Str", default => "foo");

    sub BUILD {
        my $self = shift;
        print "I was called\n";
    }
}

Foo->new;

everything works just fine (but is ugly and out of place with the rest of the code).

一切正常(但是丑陋且与其余代码不合适)。

3 个解决方案

#1


BUILD takes an arg, if you don't need it, just say:

如果你不需要,BUILD会采取arg,只需说:

method BUILD($) { ... }

#2


It's failing because BUILD requires a one-arg method signature. By default, MooseX::Declare creates a signature which is not compatible with the way BUILD is called. (The details are murky to me.) I know because I ran into a similar error once. I certainly agree the error message could be more enlightening; that's true with a lot of Moose stuff.

它失败了因为BUILD需要一个arg方法签名。默认情况下,MooseX :: Declare创建的签名与BUILD的调用方式不兼容。 (细节对我来说很模糊。)我知道因为我遇到过类似的错误一次。我当然同意错误信息可能更具启发性;很多Moose的东西都是如此。

Anyway, I got it to work like this:

无论如何,我让它像这样工作:

use MooseX::Declare;

class Foo {
    has foo => (is => "rw", isa => "Str", default => "foo");

    method BUILD(Item $href) {
        print "I was called\n";
    }
}

Foo->new;

Hope that helps.

希望有所帮助。

You can fiddle with the signature and try more specific types; I think Moose sends a hashref of the as-yet-unblessed object as the parameter.

您可以摆弄签名并尝试更具体的类型;我认为Moose发送了一个尚未完成的对象的hashref作为参数。

#3


Perl understands sub and so an entry into the current package's symbol table is made. &Foo::BUILD, after Devel::Declare and other magic has created a package scope from the class closure.

Perl理解sub,因此可以进入当前包的符号表。 &Foo :: BUILD,在Devel :: Declare和其他魔法之后从类闭包中创建了一个包范围。

Moose specifically looks for the BUILD sub to allow you to manipulate constructor logic. My guess (although I haven't traced it all the way through) is that the MooseX modules stay out of the way of what Moose is trying to do. So that a native BUILD is forever passed to the Moose magic to determine constructor logic.

Moose专门寻找BUILD子,以允许您操纵构造函数逻辑。我的猜测(虽然我还没有完全追溯)是MooseX模块不会像Moose那样做。因此,本机BUILD永远传递给Moose魔法来确定构造函数逻辑。

On the other hand the method keyword is more Devel::Declare magic to create methods in the meta class structure.

另一方面,method关键字更多是Devel :: Declare魔术,用于在元类结构中创建方法。

#1


BUILD takes an arg, if you don't need it, just say:

如果你不需要,BUILD会采取arg,只需说:

method BUILD($) { ... }

#2


It's failing because BUILD requires a one-arg method signature. By default, MooseX::Declare creates a signature which is not compatible with the way BUILD is called. (The details are murky to me.) I know because I ran into a similar error once. I certainly agree the error message could be more enlightening; that's true with a lot of Moose stuff.

它失败了因为BUILD需要一个arg方法签名。默认情况下,MooseX :: Declare创建的签名与BUILD的调用方式不兼容。 (细节对我来说很模糊。)我知道因为我遇到过类似的错误一次。我当然同意错误信息可能更具启发性;很多Moose的东西都是如此。

Anyway, I got it to work like this:

无论如何,我让它像这样工作:

use MooseX::Declare;

class Foo {
    has foo => (is => "rw", isa => "Str", default => "foo");

    method BUILD(Item $href) {
        print "I was called\n";
    }
}

Foo->new;

Hope that helps.

希望有所帮助。

You can fiddle with the signature and try more specific types; I think Moose sends a hashref of the as-yet-unblessed object as the parameter.

您可以摆弄签名并尝试更具体的类型;我认为Moose发送了一个尚未完成的对象的hashref作为参数。

#3


Perl understands sub and so an entry into the current package's symbol table is made. &Foo::BUILD, after Devel::Declare and other magic has created a package scope from the class closure.

Perl理解sub,因此可以进入当前包的符号表。 &Foo :: BUILD,在Devel :: Declare和其他魔法之后从类闭包中创建了一个包范围。

Moose specifically looks for the BUILD sub to allow you to manipulate constructor logic. My guess (although I haven't traced it all the way through) is that the MooseX modules stay out of the way of what Moose is trying to do. So that a native BUILD is forever passed to the Moose magic to determine constructor logic.

Moose专门寻找BUILD子,以允许您操纵构造函数逻辑。我的猜测(虽然我还没有完全追溯)是MooseX模块不会像Moose那样做。因此,本机BUILD永远传递给Moose魔法来确定构造函数逻辑。

On the other hand the method keyword is more Devel::Declare magic to create methods in the meta class structure.

另一方面,method关键字更多是Devel :: Declare魔术,用于在元类结构中创建方法。