【问题标题】:Why same function call bring different results in object internals?为什么相同的函数调用会在对象内部带来不同的结果?
【发布时间】:2017-09-17 04:10:26
【问题描述】:

我正在使用 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
    }
}

而这个(通过$a->generate在外部调用generate sub)不会:

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: {}
}

程序返回错误:

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

【问题讨论】:

  • 因为当您调用 $a->generate 时,您将此属性添加到 Cat 类,而不是此类 Cat ($a) 的实例。即使您添加到实例(对象),该字段也不会被初始化。

标签: perl oop code-generation moose


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    相关资源
    最近更新 更多