2010-12-09 18 views
7

¿Cuál es la diferencia entre el ref($object) incorporado y el Scalar::Utilblessed($object)? ¿Se prefiere uno sobre el otro?Scalar :: Util vs ref function

use strict; 
use warnings; 

use Scalar::Util qw(blessed isvstring); 

my $object = foo->new(); 

print "Object is a " . blessed($object) . "\n"; 
print "Object is a " . ref($object) . "\n"; 

my $version = 5.00.03; 

print "Version is a " . ref(\$version) . "\n"; 
if (isvstring($version)) { 
    print "Version is a VSTRING\n"; 
} 

package foo; 
sub new { 
    my $class = shift; 
    my $self = {}; 

    bless($self, $class); 
    return $self; 
} 
+0

Vea también: http://stackoverflow.com/questions/1399833/how-can-i-get-perls-ref-function-to-return-ref-io-and-lvalue/1400176#1400176 –

Respuesta

7

De acuerdo con POD, blessed() sólo funciona en las referencias benditos (por ejemplo, un pasado a una llamada bless() referencias).

Devuelve undef en todo lo demás, incluyendo referencias de hash/matriz donde ref() vuelve HASH/ARRAY (y un montón de otros tipos como delineado en perldoc ref). Para obtener el tipo de referencia, puede, por supuesto, llamar al Scalar::Util::reftype.

En cuanto a si uno debe usarse sobre otro, creo que depende en gran medida de lo que es la lógica.

  • Si única desea distinguir las referencias reales benditos de todo lo demás, blessed() proporciona una manera más concisa que tomar una ref y luego verificar que el valor no es el de los estándar devueltos por referencia sin bendición.

    my $ref_type = ref($my_ref); 
    print "USING REF: "; 
    if (  $ref_type 
         && $ref_type ne ref({}) 
         && $ref_type ne ref([]) 
         && $ref_type ne "SCALAR" 
         # Could also use a hash with all allowed values of ref() instead 
         && $ref_type !~ /^(CODE|REF|GLOB|...)$) { 
        print "I am an object of class $ref_type\n"; 
    } else { 
        print "I'm a reference of type $ref_type\n"; 
    } 
    
    
    # vs... 
    
    
    print "USING SCALAR_UTIL: "; 
    my $ref_type = blessed($my_ref); 
    print $ref_type ? "I am an object of class $ref_type\n" 
           : "I am a reference of type " . reftype($my_ref) . "\n"; 
    
  • Si necesita distinciones sutiles entre ambas referencias bendito y los diferentes ublessed, entonces una sola llamada ref() es más concisa que una combinación de blessed y reftype.

  • caso un borde donde hay una diferencia funcional real entre los dos enfoques, como se ha señalado en los comentarios de Eric Strom, es cuando alguien crea una clase que coincide con uno de ref()hardcoded values (por ejemplo bless [], 'HASH' - en cuyo caso son o Mudo tonto o demasiado inteligente por la mitad).

    my $sssft = bless [], 'HASH'; # sssft = someone_should_suffer_for_this 
    ref_description_using_ref($sssft); 
    ref_description_using_scalar_util($sssft); 
    
    
    # OUTPUT: 
    USING REF: I'm a reference of type HASH 
    USING SCALAR_UTIL: I am an object of class HASH 
    

Exención de responsabilidad: Sobre la base de la documentación, no debería haber ninguna diferencia entre los dos cuando el argumento es una referencia bendito en una clase (por ejemplo, devuelve nombre de clase). Pero no he verificado la fuente "Scalar :: Util" para confirmar.

+4

Y en la otra cara, 'Scalar :: Util :: reftype' devuelve el tipo de referencia subyacente (por ejemplo,' HASH' o 'GLOB' o lo que sea), incluso si su argumento es bendecido. Básicamente 'reftype' y' blessed' desacoplan las dos cosas diferentes que el 'ref' incorporado intenta hacer. – hobbs

+1

no hay nada que le impida a alguien escribir 'bless [], 'HASH'' u otra locura que causará errores si solo usa' ref'. ahí es donde 'blessed' y 'reftype' son útiles –

+0

@Eric Strom: si usar' ref' provoca errores depende de cuán ingenuamente uno procese su salida. 'HASH = ARRAY (0x182a35c)' parece extraño pero * puede * extraer correctamente la clase y el tipo de referencia antes de romper las rótulas del sociópata que nombró una clase "HASH". –