그냥 첨부 할 경우! 기능을 특정 객체에 추가하고 상속 할 필요가없는 경우 객체에 코드 참조를 저장하고 호출 할 수 있습니다.
# Store the code in the object, putting it in its own
# nested hash to reduce the chance of collisions.
$obj->{__actions}{something} = sub { ... };
# Run the code
my @stuff = $obj->{__actions}{something}->(@args);
문제는 $obj->{__actions}{something}
에 코드 참조가 있는지 확인해야합니다. 내가 제안하는 것은이 절차를 둘러싼 메소드를 랩핑하는 것이다.
sub add_action {
my($self, $action, $code) = @_;
$self->{__actions}{$action} = $code;
return;
}
sub take_action {
my($self, $action, $args) = @_;
my $code = $self->{__actions}{$action};
return if !$code or ref $code ne 'CODE';
return $code->(@$args);
}
$obj->add_action("something", sub { ... });
$obj->take_action("something", \@args);
당신은 이미 당신이로 방법을 주입 정상적으로 서브 루틴을 작성하지만, 완전한 이름을 사용할 클래스 이름을 알고있는 경우. 서브 루틴 내부에 전역이 하지 일부 :: 클래스에서, 주변의 패키지에 될 것
는
sub Some::Class::new_method {
my $self = shift;
...
}
참고. 영구 변수를 원한다면 서브 루틴 내에 state
을 사용하거나 서브 루틴 외부에 my
을 사용하십시오. 당신이 컴파일시에 이름을 모르는 경우 당신이 마지막에 가까웠다 있도록
, 당신은, 심볼 테이블에 서브 루틴을 주입해야합니다.
sub inject_method {
my($object, $method_name, $code_ref) = @_;
# Get the class of the object
my $class = ref $object;
{
# We need to use symbolic references.
no strict 'refs';
# Shove the code reference into the class' symbol table.
*{$class.'::'.$method_name} = $code_ref;
}
return;
}
inject_method($obj, "new_method", sub { ... });
Perl의 메소드는 객체가 아닌 클래스와 연관되어 있습니다. 단일 객체에 메소드를 할당하려면 해당 객체를 자체 클래스에 넣어야합니다.위와 비슷하지만 모든 인스턴스에 대해 하위 클래스를 만들어야합니다.
my $instance_class = "_SPECIAL_INSTANCE_CLASS_";
my $instance_class_increment = "AAAAAAAAAAAAAAAAAA";
sub inject_method_into_instance {
my($object, $method_name, $code_ref) = @_;
# Get the class of the object
my $old_class = ref $object;
# Get the special instance class and increment it.
# Yes, incrementing works on strings.
my $new_class = $instance_class . '::' . $instance_class_increment++;
{
# We need to use symbolic references.
no strict 'refs';
# Create its own subclass
@{$new_class.'::ISA'} = ($old_class);
# Shove the code reference into the class' symbol table.
*{$new_class.'::'.$method_name} = $code_ref;
# Rebless the object to its own subclass
bless $object, $new_class;
}
return;
}
나는 인스턴스가 이미 클래스가 /^${instance_class}::/
일치하는 경우 확인하여이 치료를했다 여부를 확인하는 코드를 떠났다. 나는 그것을 당신을위한 운동으로 남겨 둡니다. 모든 객체에 대해 새로운 클래스를 만드는 것은 비용이 적게 들고 비용이 많이 듭니다.
유효한 이유가 있지만 예외적입니다. 이 종류의 monkey patching을 수행해야하는지 여부에 대해 정말로 질문해야합니다. 일반적으로 action at a distance은 피해야합니다.
하위 클래스, 위임 또는 역할을 사용하여 동일한 작업을 수행 할 수 있습니까?
당신을 위해 훨씬 더 많은 것을 할 Perl OO 시스템이 이미 존재합니다. 당신은 하나를 사용해야합니다. Moose, Moo (Role::Tiny 통해) 및 Mouse은 모두 인스턴스에 역할을 추가 할 수 있습니다.
클래스의 모든 개체가 아닌 특정 개체에 추가 메서드를 추가 하시겠습니까? 하위 클래스를 만들 수없는 이유가 무엇입니까? – ysth
개체에는 메서드가 없으며 클래스에는 메서드가 있습니다. – ikegami
@ikegami : 귀하의 모델에 따라 다릅니다. 당신이 정말로 신경 쓰는 것은 인스턴스가 클래스에 의해 지정된 모든 메소드를 가지고 있다는 것입니다. Ruby에는 클래스에 정의되어 있지만 해당 클래스의 인스턴스를 통해서만 사용할 수있는 클래스 메소드 (인스턴스가 아닌 클래스에서만 호출 할 수 있음)와 인스턴스 메소드가 있습니다. 또한 주어진 인스턴스에 고유 한 * 싱글 톤 메소드 *가 있는데,이 OP가 필요로하는 것입니다. – Borodin