2014-10-12 37 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