Perl에서 원숭이를 맞추는 방법의 원래 메소드에 액세스하려면 어떻게해야합니까?
-
05-09-2019 - |
문제
나는 노력하고있다 원숭이 패치 Perl 클래스 : 기존 방법의 동작을 변경하고 싶습니다.
Perlmonks 의이 노드 방법을 보여줍니다 추가하다 기존 클래스에 대한 기능. 이 패턴은 기존 기능에 대한 새로운 구현을 제공하는 데 사용될 수 있음을 발견했습니다.
그러나 원래 기능을 호출하는 방법을 알고 싶습니다.
나는 다음과 같은 것을 찾고 있습니다.
use ExistingClass;
# TODO: Somehow rename existingFunction() to oldExistingFunction().
sub ExistingClass::existingFunction {
my $self = shift;
# New behavior goes here.
$self->oldExistingFunction(@_); # Call old behavior.
# More new behavior here.
}
해결책
TypEglob 할당
*ExistingClass::oldExistingFunction = *ExistingClass::existingFunction;
빠르고 더럽습니다. 이 별명은 모두입니다 existingFunction
상징 oldExistingFunction
. 여기에는 관심있는 서브뿐만 아니라 같은 이름을 가질 수있는 스칼라, 어레이, 해시, 핸들이 포함됩니다.
- 장점 : 생각이없고 효과가 있습니다. "빠른"
- 단점 : "더러운"
Coderef 할당
*ExistingClass::oldExistingFunction = \&ExistingClass::existingFunction;
# or something using *ExistingClass::symbol{CODE}
그 사람은 서브를 별칭 만합니다. 여전히 패키지 stash에서 완료되었습니다. oldExistingFunction
상징은 전 세계적으로 보이며 원하는 것이 될 수도 있고 아닐 수도 있습니다. 아마 그렇지 않을 것입니다.
- 장점 : 그 별칭은 다른 변수 유형에 '누출'되지 않습니다.
- 단점 : 더 많은 생각, 더 많은 타이핑. *... {code} 구문을 찾는 경우 훨씬 더 많은 생각
어휘 coderef
my $oldFunction = \&ExistingClass::existingFunction;
사용 my
Current Block/File에만 볼 수있는 이전 함수에 대한 참조를 유지합니다. 외부 코드가 더 이상 도움없이이를 보유 할 수있는 방법은 없습니다. 전화 컨벤션을 염두에 두십시오.
$self->$oldFunction(@args);
$oldFunction->($self, @args);
- 장점 : 더 이상 가시성 문제가 없습니다
- 단점 : 제대로하기가 더 어렵습니다
엘크
보다 JROCKWAY의 답변. 더 이상 지구 및/또는 참조와 관련이 없기 때문에 올바른 방법이되어야하지만 설명하기에 충분히 알지 못합니다.
다른 팁
당신은 사용해야합니다 엘크 또는 클래스 :: 메소드 :: 수정 자.
이 경우, 당신은 다음과 같이 말할 수 있습니다.
around 'some_method' => sub {
my ($orig, $self, @args) = @_;
# ... before original ...
$self->$orig(@_);
# ... after original ...
};
메모에 이것의 좋은 예입니다.
어휘 변수로 복사하여 호출하십시오.
my $existing_function_ref = \&ExistingClass::existingFunction;
*ExistingClass::existingFunction = sub {
my $self = shift;
$self->go_and_do_some_stuff();
my @returns = $existing_function_ref->( $self, @_ );
$self->do_some_stuff_with_returns( @returns );
return wantarray ? @returns : shift @returns;
};
oo-syntax로 더 나은 느낌이 들면 UNIVERSAL::apply
방법 (또는 선택한 기본 클래스에서).
sub UNIVERSAL::apply {
my ( $self, $block ) = splice( @_, 0, 2 );
unshift @_, $self;
goto &$block;
}
그렇게하면 다음과 같이 부를 수 있습니다.
my @returns = $self->apply( $existing_function_ref, @_ );
을 위한 엘크 수업, 당신은 그냥 할 수 있습니다 JROCKWAY의 말을하십시오; 무모스 수업의 경우 다음을 수행하십시오.
use Class::MOP ();
use ExistingClass;
Class::MOP::Class->initialize('ExistingClass')->add_around_method_modifier(
existingFunction => sub {
my $orig = shift;
# new behaviour goes here
# call old behaviour
my $result = $orig->(@_);
# more new behaviour goes here
}
);
대조적으로 다음과 같은 문제가 있습니다.
package NewClass;
use base qw/ExistingClass/;
sub existingFunction {
# ....
}
sub oldExistingFunction {
my $self = shift;
return $self->SUPER::existingFunction(@_);
}