2013-08-13 4 views
7

C'è un modo per determinare se una subroutine è invocata come metodo (con probing @ISA) o come subroutine semplice? Forse con una sorta di modulo di estensione super- caller()?In Perl, come posso determinare se una subroutine è stata invocata come metodo?

Ad esempio, dato

package Ad::Hoc; 

sub func() { ... } 

Come può func() discriminare tra i due seguenti invocazioni:

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

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

(lo so, la voglia di fare questo è un'indicazione Probabile di cattiva progettazione ™.)

risposta

10

Vedere se Devel::Caller aiuta. Ho cambiato il codice per richiamare func su un oggetto e sembra funzionare sul mio Mac con perl 5.14.3 (e 5.24.0):

called_as_method($level)

called_as_method returns vero se la subroutine a $level è stato chiamato come metodo

#!/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(); 

uscita:

method 
function
+3

Ma è necessario usarlo solo se il metodo accetta un numero variabile di argomenti. Altrimenti, puoi semplicemente controllare la dimensione di '@ _'. – ikegami

+0

+1 molto promettente. Ottengo un fatale errore "pushmark o pad" se provo '$ blessed-> func' con' called_as_method() '(5.18.0, PadWalker-1.96, D :: Caller-2.06), ma l'invocazione del" metodo del pacchetto " funziona perfettamente, come illustrato sopra. – pilcrow

+0

@ikegami, d'accordo. Questa è una curiosità tecnica derivata da un problema che probabilmente non avrebbe dovuto essere consentito in primo luogo. – 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

Come funziona questo discriminare annuncio :: Hoc-> func da func ('Ad Hoc ::'), o $ o-> func() da func ($ o)? – pilcrow

+1

@pilcrow, 'ref 'Ad :: Hoc'' non restituirà'' Ad :: Hoc'' ... – kjprice

+0

@pilcrow, sì, perché sei il secondo caso, non lo so. Se lo stai scrivendo, forse dovresti solo passare una bandiera aggiuntiva. – kjprice