UNIVERSAL - 所有类的基类(受祝福的引用)
my $obj_is_io = $fd->isa("IO::Handle");
my $cls_is_io = Class->isa("IO::Handle");
my $obj_does_log = $obj->DOES("Logger");
my $cls_does_log = Class->DOES("Logger");
my $obj_sub = $obj->can("print");
my $cls_sub = Class->can("print");
my $eval_sub = eval { $ref->can("fandango") };
my $ver = $obj->VERSION;
# but never do this!
my $is_io = UNIVERSAL::isa($fd, "IO::Handle");
my $sub = UNIVERSAL::can($obj, "print");
UNIVERSAL
是所有受祝福的引用继承的基类。请参阅 perlobj。
UNIVERSAL
提供以下方法
$obj->isa( TYPE )
CLASS->isa( TYPE )
eval { VAL->isa( TYPE ) }
其中
当用作实例或类方法($obj->isa( TYPE )
)时,如果 $obj 已祝福进入程序包 TYPE
或继承自程序包 TYPE
,isa
返回 true。
当用作类方法(CLASS->isa( TYPE )
,有时称为静态方法)时,如果 CLASS
继承自(或本身是)程序包 TYPE
的名称或继承自程序包 TYPE
,isa
返回 true。
如果您不确定自己拥有什么(VAL
情况),请将方法调用包装在 eval
块中,以在 VAL
未定义或未祝福的引用时捕获异常。在这种情况下,isa
运算符 是一个替代项,它只返回 false,因此不需要 eval
。
如果您想确保将 isa
作为方法调用,而不是类,请首先使用 Scalar::Util 中的 blessed
检查调用项
use Scalar::Util 'blessed';
if ( blessed( $obj ) && $obj->isa("Some::Class") ) {
...
}
$obj->DOES( ROLE )
CLASS->DOES( ROLE )
DOES
检查对象或类是否执行角色 ROLE
。角色是一组命名的特定行为(通常是特定名称和签名的方法),类似于类,但本身不一定是一个完整的类。例如,日志记录或序列化可能是角色。
DOES
和 isa
类似,因为如果两者都是 true,您就知道您调用方法的对象或类可以执行特定行为。但是,DOES
与 isa
的不同之处在于它不关心调用项如何执行操作,而只关心它是否执行操作。(当然,isa
要求有继承关系。其他关系包括聚合、委派和模拟。)
默认情况下,Perl 中的类只执行 UNIVERSAL
角色,以及继承中所有类的角色。换句话说,默认情况下,DOES
对 isa
的响应是相同的。
角色和类之间存在关系,因为每个类都暗示存在一个同名角色。继承和角色之间也存在关系,因为从祖先类继承的子类隐式地执行其父类执行的任何角色。因此,您可以安全地使用 DOES
代替 isa
,因为它将在 isa
返回 true 的所有地方返回 true(前提是任何被覆盖的 DOES
和 isa
方法的行为都适当)。
$obj->can( METHOD )
CLASS->can( METHOD )
eval { VAL->can( METHOD ) }
can
检查对象或类是否有一个名为 METHOD
的方法。如果有,则返回对子程序的引用。如果没有,则返回 undef。这包括由 $obj
、CLASS
或 VAL
继承或导入的方法。
can
无法知道对象是否能够通过 AUTOLOAD 提供方法(除非对象的类已适当地覆盖 can
),因此返回值 undef 并不一定意味着对象将无法处理方法调用。为了解决这个问题,一些模块作者使用前向声明(参见 perlsub)来处理他们将通过 AUTOLOAD 处理的方法。对于这样的“虚拟”子程序,can
仍将返回一个代码引用,当调用该引用时,它将进入 AUTOLOAD。如果没有提供合适的 AUTOLOAD,则调用代码引用将导致错误。
您可以将 can
作为类(静态)方法或对象方法调用。
同样,关于拥有有效调用者的规则也适用——如果您需要格外偏执,请使用 eval
块或 blessed
。
VERSION ( [ REQUIRE ] )
VERSION
将返回对象被祝福进入的包中的变量 $VERSION
的值。如果给出了 REQUIRE
,那么它将进行比较,如果包版本不大于或等于 REQUIRE
,或者 $VERSION
或 REQUIRE
都不属于“宽松”版本号(由 version 模块定义),那么它将死亡。
VERSION
的返回实际上将是使用包 $VERSION
标量字符串化的版本对象,该对象保证是等效的,但可能不是 $VERSION
标量的精确内容。如果您想要 $VERSION
的实际内容,请改用 $CLASS::VERSION
。
VERSION
可以作为类(静态)方法或对象方法调用。
注意: can
直接使用 Perl 的内部代码进行方法查找,而 isa
使用非常相似的方法和缓存策略。如果 Perl 代码动态地更改任何包中的 @ISA,这可能会导致奇怪的影响。
您可以通过 Perl 或 XS 代码向 UNIVERSAL 类添加其他方法。您不需要 use UNIVERSAL
来使这些方法对您的程序可用(您也不应该这样做)。
无。
此文档的先前版本建议使用 isa
作为函数来确定引用的类型
$yes = UNIVERSAL::isa($h, "HASH");
$yes = UNIVERSAL::isa("Foo", "Bar");
问题在于,此代码永远不会在任何类中调用重写的 isa
方法。相反,对于第一种情况,请使用 Scalar::Util 中的 reftype
use Scalar::Util 'reftype';
$yes = reftype( $h ) eq "HASH";
以及 isa
的方法形式对于第二种情况
$yes = Foo->isa("Bar");