2014-10-12 60 views
0

我需要为Moose类实例添加属性。在下面的代码中,当我创建类Child的实例并向其添加属性“app”时,我发现在创建下一个实例时也添加了此属性。我做错了,我需要每个创建实例的属性。Perl Moose添加实例属性无类属性

#!C:\perl\bin\perl.exe 
#!/usr/bin/perl 

use v5.10; 
use Moose; 
use Data::Dumper; 

{ 
    package Child; 

    use Moose; 
    use utf8; 

    sub name { 
     say "My name is Richard"; 
    } 
} 

sub add_attribute { 
    my ($object, $attr) = @_; 

    my $meta = $object->meta; 

    if (!$object->can("app")) { 
     $meta->add_attribute(app => (is => 'rw', default => sub{$attr})); 
     $object->app($attr); 
    } 
    else { 
     #$object->app($attr); 
     say "attr $attr already exists: object=". ref($object) . ", attr=".($object->app); 
    } 
} 

my $child = Child->new; 
$child->name; 
add_attribute($child, "First"); 
say "Child Attr: " . $child->app; 
say ""; 
say Dumper($child); 

my $child1 = Child->new; 
$child1->name; 
#add_attribute($child1, "Second"); 
say "Child1 Attr: " . $child1->app; 
say Dumper($child1); 
#say Dumper($child1->meta); 

输出:

My name is Richard 
Child Attr: First 

$VAR1 = bless({ 
       'app' => 'First' 
       }, 'Child'); 

My name is Richard 
Child1 Attr: First 
$VAR1 = bless({ 
       'app' => 'First' 
       }, 'Child'); 
+0

你打算如何在实例上创建方法?在基于类的对象系统中,这意味着什么? – 2014-10-12 13:02:26

+0

据我所知,Moose属性存储在对象实例的哈希中,所以如果我在第一个实例中添加一个属性,为什么这个属性也存在于下一个创建的实例中,这个问题呢?我的问题现在清楚了吗? – daliaessam 2014-10-12 13:09:56

回答

4

关键是要创建原始类的新的子类,属性添加到这一点,那么rebless实例到新的子类。下面是一个例子:

use v5.14; 

package Person { 
    use Moose; 
    has name => (is => 'ro'); 
} 

sub add_attribute { 
    my ($obj, $name, $value) = @_; 
    my $new_class = Moose::Meta::Class->create_anon_class(
    superclasses => [ ref($obj) ], 
); 
    $new_class->add_attribute($name, is => 'rw'); 
    $new_class->rebless_instance($obj, $name => $value); 
} 

my $alice = Person->new(name => 'Alice'); 
my $bob = Person->new(name => 'Bob'); 

add_attribute($alice, foot_size => 6); 

say $alice->foot_size; 

say $bob->foot_size; # dies, no such method 
+0

问题是为什么如果Moose将属性存储在对象内部的散列中,这些属性将添加到所有实例中,这些属性是属性还是属性? – daliaessam 2014-10-12 18:23:52

+1

Moose将属性**值**存储在对象的哈希中,但访问这些值的**方法**被添加到类中,因此可以在类的任何实例上调用。例如,Alice的脚尺寸的“6”存储在Alice的散列中。但是getter/setter方法已被添加到Alice的类中,所以同一类的任何其他对象也可以有一个尺寸(可能小于或大于“6”)。这就是为什么我们需要将Alice拉入新班级,以阻止Bob获得'foot_size'方法。 – tobyink 2014-10-12 18:33:44

+0

是的我现在明白了,你说得很清楚。但是为什么这种技术并不坏,它应该被添加到请求的实例中,只是我们称之为对象的元。 – daliaessam 2014-10-12 18:59:26