2014-10-12 2 views
0

무스 클래스 인스턴스에 속성을 추가해야합니다. 아래 코드에서 Child 클래스의 인스턴스를 만들고 "app"속성을 추가하면 다음 인스턴스를 만들 때이 속성도 추가됩니다. 내가 뭘 잘못했는지, 다시 한번 나는 생성 된 인스턴스마다 속성이 필요하다.Perl 무스 클래스 속성이 아닌 인스턴스 속성 추가

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

까지 내가 알기로 무스 속성은 객체 인스턴스의 해시에 저장되므로 첫 번째 인스턴스에 속성을 추가하면 왜이 속성도 다음에 생성 된 인스턴스에도 존재합니까? 제 질문은 지금 분명합니까? – 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는 객체의 해시 안에 ** 속성 ** 값 **을 저장하지만 해당 값에 액세스하는 ** 메소드 **는 클래스에 추가되므로 클래스의 모든 인스턴스에서 호출 할 수 있습니다. 예를 들어 Alice의 발 크기에 대한 "6"은 Alice의 해시에 저장됩니다. 그러나 getter/setter 메서드가 Alice의 클래스에 추가되었으므로 동일한 클래스의 다른 모든 객체도 발 크기 ("6"보다 작거나 클 수 있음)를 가질 수 있습니다. 그래서 우리는 Bob이'foot_size' 메소드를 얻는 것을 막기 위해 Alice를 새로운 클래스로 끌어 올 필요가있었습니다. – tobyink

+0

예, 이해했습니다. 매우 분명합니다. 그러나이 기술이 왜 그리 좋지 않은지, 우리가 객체의 메타를 호출 할 때만 요청 된 인스턴스에 추가되어야합니다. – daliaessam