Perl에서 원숭이를 맞추는 방법의 원래 메소드에 액세스하려면 어떻게해야합니까?

StackOverflow https://stackoverflow.com/questions/575710

  •  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 ...
};

다른 답변 외에도 다음과 같은 모듈을보십시오.

나는 또한 "동적 언어"장에서 이것에 대해 이야기합니다. 마스터 링 Perl.

메모에 이것의 좋은 예입니다.

어휘 변수로 복사하여 호출하십시오.

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(@_);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top