Scalar :: Util vs. ref function - PullRequest
       8

Scalar :: Util vs. ref function

7 голосов
/ 09 декабря 2010

В чем разница между встроенными ref($object) и Scalar::Util blessed($object)? Один предпочтительнее другого?

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

1 Ответ

8 голосов
/ 10 декабря 2010

Согласно POD, blessed() работает только для благословенных ссылок (например, ссылок, переданных на вызов bless()).

Возвращает undef для всего остального, включая ссылки на хеш / массив, где ref() возвращает HASH / ARRAY (и множество других типов, как указано в perldoc ref ). Чтобы получить справочный тип, вы можете, конечно, позвонить Scalar::Util::reftype.

Что касается того, следует ли использовать один над другим, я думаю, что это в значительной степени зависит от логики.

  • Если вы только хотите отличить настоящие благословенные ссылки от всего остального, blessed() предоставляет более краткий способ, чем взятие ref, а затем проверка того, что значение не соответствует стандартному возвращенные по неподтвержденной ссылке.

    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";
    
  • Если вам нужны точные различия как между благословенными ссылками, так и с разными ublessed ссылками, то один ref() вызов является более кратким, чем комбинация blessed и reftype.

  • Один крайний случай, когда существует реальная функциональная разница между двумя подходами, как отмечено в комментариях Эрика Строма, - это когда кто-то создает класс, который соответствует одному из ref() жестко закодированных значений (например, bless [], 'HASH' - в этом случае они либо тупые, либо слишком умные вдвое).

    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
    

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: На основании документации не должно быть никакой разницы между этими двумя, когда аргумент является ссылкой, благословленной в классе (например, он возвращает имя класса). Но я не проверял источник "Scalar :: Util" для подтверждения.

...