2009-01-20 19 views
6

Tengo una matriz polimórfica de objetos que implementan dos interfaces (informales). Quiero ser capaz de diferenciarlos con la reflexión a lo largo de las líneas de:¿Cómo puedo determinar si un objeto implementa un método en Perl?

if (hasattr(obj, 'some_method')) { 
    # `some_method` is only implemented by one interface. 
    # Now I can use the appropriate dispatch semantics. 
} else { 
    # This must be the other interface. 
    # Use the alternative dispatch semantics. 
} 

tal vez algo como esto funciona ?:

if (*ref(obj)::'some_method') { 
    # ... 

tengo dificultad para distinguir cuando la sintaxis intentará invocar una subrutina y cuando devolverá una referencia de subrutina. No estoy muy familiarizado con las tablas de símbolos de paquetes ATM y solo estoy tratando de hackear algo. :-)

Gracias de antemano!

Respuesta

16
use Scalar::Util qw(blessed); 
if(blessed($obj) and $obj->can('some_method')){ 

} 

"puede" aquí es un método heredado por todas las clases de UNIVERSAL. Las clases pueden anular este método, pero no es una buena idea hacerlo.

Además, "puede" devuelve una referencia a la función, por lo que puede hacer:

$foo->can('some_method')->($foo , @args); 

o

my $sub = $foo->can('some_method'); 
$foo->$sub(@args); 

Editar Sintaxis de cadena actualizada, gracias a Brian Phillips

+0

¿Es 'can' un nombre de método reservado de alguna manera, o simplemente te disparas en el pie si lo implementas? – cdleary

+0

No olvide que necesita pasar explícitamente el objeto a la referencia de función devuelta por can: $ foo-> can ('some_method') -> ($ foo, @args). Alternativamente, my $ sub = $ foo-> can ('some_method'); $ foo -> $ sub (@args); –

+0

Una orden judicial general contra la 'lata' primordial es un poco fuerte. Hay buenas e importantes razones para hacerlo. – darch

Cuestiones relacionadas