2013-08-13 8 views
7

Czy istnieje sposób określenia, czy podprogram jest wywoływany jako metoda (z sondowaniem @ISA), czy jako zwykły podprogram? Być może z jakimś modułem rozszerzenia super-caller()?W Perlu, w jaki sposób określić, czy podprogram został wywołany jako metoda?

Na przykład, biorąc pod uwagę

package Ad::Hoc; 

sub func() { ... } 

Jak func() rozróżnienia między dwiema następującymi inwokacji:

Ad::Hoc->func;   # or $obj->func 

Ad::Hoc::func('Ad::Hoc'); # or func($obj) 

(wiem, pragnienie, aby to zrobić jest Prawdopodobny Wskazanie słaby projekt ™.)

Odpowiedz

10

Sprawdź, czy pomaga Devel::Caller. Zmieniłem kod powołać func na obiekcie i wydaje się działać na moim Mac z perl 5.14.3 i 5.24.0) (:

called_as_method($level)

called_as_method returns true jeśli podprogram w $level nazwano jako metoda.

#!/usr/bin/env perl 

package Ad::Hoc; 
use strict; use warnings; 

use Devel::Caller qw(called_as_method); 

sub func { 
    printf "%s\n", called_as_method(0) ? 'method' : 'function'; 
    return; 
} 

package main; 
use strict; use warnings; 

Ad::Hoc->func; 
Ad::Hoc::func(); 

wyjściowa:

method 
function
+3

Ale musisz go użyć tylko wtedy, gdy metoda akceptuje zmienną liczbę argumentów. W przeciwnym razie możesz po prostu sprawdzić rozmiar '@ _'. – ikegami

+0

+1 bardzo obiecujący. Dostaję fatalny błąd "pushmark lub pad", jeśli wypróbuję '$ blessed-> func' z' called_as_method() '(5.18.0, PadWalker-1.96, D :: Caller-2.06), ale wywołanie metody pakietowej działa doskonale, jak ilustrujesz powyżej. – pilcrow

+0

@ikegami, zgodzili się. Jest to ciekawość techniczna wyrwana z problemu, który prawdopodobnie nie powinien był być dozwolony w pierwszej kolejności. – pilcrow

-2
package Ad::Hoc; 

sub foo { 
    my $self = shift; 
    if(ref($self) ne 'Ad::Hoc') { 
     unshift @_, $self; 
     undef $self; 
    } 

    if($self) { 
     # I'm a method 
    } else { 
     # I'm a sub 
    } 
} 
+0

Jak to dyskryminuje Ad :: Hoc-> func z func ('Ad Hoc ::') lub $ o-> func() z func ($ o)? – pilcrow

+1

@pilcrow, 'ref 'Ad :: Hoc'' nie zwróci'' Ad :: Hoc'' ... – kjprice

+0

@pilcrow, tak, bo to drugi przypadek, nie wiem. Jeśli to piszesz, może powinieneś po prostu przekazać dodatkową flagę. – kjprice