Scalar :: Util与ref函数

时间:2010-12-09 20:54:28

标签: perl perl-module

内置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 个答案:

答案 0 :(得分:8)

根据POD,blessed()仅适用于受祝福的引用(例如传递给bless()调用的引用)。

它会在其他所有内容上返回undef,包括哈希/数组引用ref()返回HASH / ARRAY(以及{{3中描述的一堆其他类型) }})。要获得引用类型,您当然可以调用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";
    
  • 如果您需要对受祝福的引用和不同的引用进行细微区分,则单个ref()调用比blessedreftype的组合更简洁。

  • 正如Eric Strom的评论中所指出的那样,两个方法之间存在实际功能差异的一个边缘情况是当有人创建一个与ref() perldoc 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”来源确认。