Как правильно создать метод BUILD в MooseX :: Declare? - PullRequest
5 голосов
/ 21 июля 2009

У меня проблемы с методом BUILD в MooseX :: Declare . Если я скажу:

#!/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;

Я получаю следующее менее полезное сообщение об ошибке:

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

Но если я скажу:

#!/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;

все работает просто отлично (но уродливо и неуместно с остальным кодом).

Ответы [ 3 ]

6 голосов
/ 21 июля 2009

BUILD берет аргумент, если он вам не нужен, просто скажите:

method BUILD($) { ... }
5 голосов
/ 21 июля 2009

Сбой, потому что BUILD требует подписи метода с одним аргументом. По умолчанию MooseX::Declare создает подпись, которая несовместима с тем, как вызывается BUILD. (Подробности для меня мрачны.) Я знаю, потому что однажды столкнулся с подобной ошибкой. Я, конечно, согласен, что сообщение об ошибке может быть более поучительным; это правда с большим количеством лося.

В любом случае, я заставил его работать так:

use MooseX::Declare;

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

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

Foo->new;

Надеюсь, это поможет.

Вы можете поиграть с подписью и попробовать более конкретные типы; Я думаю, что Moose отправляет в качестве параметра хэш-ссылку на еще не рассмотренный объект.

0 голосов
/ 21 июля 2009

Perl понимает sub, поэтому делается запись в таблицу символов текущего пакета. & Foo :: BUILD после Devel :: Declare и другой магии создал область пакета из замыкания класса.

Moose специально ищет сабвуфер BUILD, чтобы позволить вам манипулировать логикой конструктора. Мое предположение (хотя я не проследил это до конца) состоит в том, что модули MooseX остаются в стороне от того, что пытается сделать Moose. Так что нативный BUILD всегда передается магии лося для определения логики конструктора.

С другой стороны, ключевое слово method больше Devel :: Declare магия для создания методов в структуре мета-класса.

...