Why does the same function call produce different results in the internals of the object?

I add classes, methods and attributes dynamically using Moose :: Meta :: Class.

Can someone explain why this code works (call generate()

inside, inside, inside the class 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!'

      

conclusion p($a)

:

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

      

and this one (calling generate

sub outside, through $a->generate

) fails:

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!'

      

conclusion p($a)

:

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

      

and the program returns an error:

Cannot call method "Siberian" on undefined value in base2.pl line 39.

+3


source to share


1 answer


Since generate

not an object, but a class method, he needed to call it before new

:



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

      

0


source







All Articles