为什么相同的函数调用会在对象内部带来不同的结果?

时间:2017-04-20 13:29:40

标签: perl oop code-generation moose

我使用Moose :: Meta :: Class动态添加类,方法和属性。

有人可以解释为什么这段代码有效(在generate()类内部调用Cat子例程):

package Cat;

use Moose;

sub generate {

    my $siberian = Moose::Meta::Class->create( 'Siberian' );
    $siberian->add_method( echo => sub { print "yeah!\n" } );


    my $tiger = Moose::Meta::Class->create( 'Tiger' );
    $tiger->add_attribute(
        Siberian => {
            is      => 'ro',
            default => sub { $siberian->new_object; }
        },
    );

    __PACKAGE__->meta->add_attribute(
        Tiger => {
            is      => 'ro',
            default => sub { $tiger->new_object },
        },
    );

    print "Generation done!\n";
}

generate();


package main;

use Data::Printer;

my $a = Cat->new;

# $a->generate;
p( $a );
$a->Tiger->Siberian->echo;    # returns 'yeah!'

p($a)的输出:

Cat  {
    Parents       Moose::Object
    public methods (3) : generate, meta, Tiger
    private methods (0)
    internals: {
        Tiger   Tiger
    }
}

而这一个(通过generate在外部调用$a->generate子)并不是:

package Cat;
use Moose;

sub generate {

    my $siberian = Moose::Meta::Class->create('Siberian');
    $siberian->add_method(
        echo => sub { print "yeah!\n" }
    );

    my $tiger = Moose::Meta::Class->create('Tiger');
    $tiger->add_attribute(
        Siberian => {
            is      => 'ro',
            default => sub { $siberian->new_object; }
        },
    );

    __PACKAGE__->meta->add_attribute(
        Tiger => {
            is      => 'ro',
            default => sub { $tiger->new_object },
        },
    );

    print "Generation done!\n";

}

# generate();


package main;
use Data::Printer;

my $a = Cat->new;
$a->generate;
p($a);
$a->Tiger->Siberian->echo; # returns 'yeah!'

p($a)的输出:

Cat  {
    Parents       Moose::Object
    public methods (3) : generate, meta, Tiger
    private methods (0)
    internals: {}
}

并且程序返回错误:

  

无法调用方法" Siberian"在base2.pl行上的未定义值   39。

1 个答案:

答案 0 :(得分:0)

由于generate不是对象,而是类方法,因此需要在new之前调用它:

Cat->generate;
my $a = Cat->new;