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

Как вы собираетесь создавать методы на экземпляре? Что это означало бы в контексте объектной системы на основе классов? –

+0

Насколько я понимаю, атрибуты Moose хранятся в хеше в экземпляре объекта, поэтому вопрос, добавляю ли я атрибут в первом экземпляре, почему этот атрибут также существует в следующих созданных экземплярах? Является ли мой вопрос ясным сейчас? – daliaessam

ответ

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

+1

Moose хранит атрибуты ** значения ** внутри хэша объекта, но ** методы ** для доступа к этим значениям добавляются в класс, поэтому их можно вызвать в любом экземпляре класса. Например, размер «6» для ног Алисы хранится в хеше Алисы. Но метод getter/setter был добавлен в класс Алисы, поэтому любые другие объекты одного и того же класса могут также иметь размер стопы (который может быть меньше или больше, чем «6»). Вот почему нам нужно было вытащить Алису в новый класс, чтобы не допустить, чтобы Боб тоже получал метод «foot_size». – tobyink

+0

Да, я понимаю, вы сказали это очень ясно. Но почему этот метод, не так ли, должен быть добавлен к запрашиваемому экземпляру только по мере того, как мы называем мета на объекте. – daliaessam