Perl有一个内部的伪模块,称为UNIVERSAL
,所有模块都从该伪模块继承。它有一个来自the docs on UNIVERSAL
的名为DOES
的方法。
$obj->DOES( ROLE )
CLASS->DOES( ROLE )
DOES
检查对象或类是否扮演角色ROLE
。角色是特定行为的命名组(通常是特定名称和签名的方法),类似于类,但本身不一定是完整的类。例如,日志记录或序列化可能是角色。
DOES
和isa
相似,因为如果二者均为真,则您知道调用该方法的对象或类可以执行特定的行为。但是,DOES
与isa
的不同之处在于,它并不关心被调用方如何执行操作,而只是在乎。 (isa
当然要求继承关系。其他关系包括聚合,委派和模拟。)角色和类之间存在关系,因为每个类都隐含着同名角色。继承和角色之间也存在关系,因为从祖先类继承的子类隐式执行其父级执行的任何角色。因此,您可以安全地使用
DOES
代替isa
,因为它会在isa
返回true的所有地方都返回true(假设任何覆盖的DOES
和{{1 }}方法的行为正确)。
我知道Moose等人提供了isa
,并且我知道如何使用它。但是就DOES
而言,UNIVERSAL::DOES
是什么?如何跟踪它们?他们如何创建除了驼鹿以外的地方来满足ROLE
?我尝试查找源代码,但the implementation of DOES
was not provided。这种DOES
的概念是否在ROLE
perl中?这似乎与perldoc perlapi
's mention of sv_does_sv
(also sv_does
/sv_does_pv
)
CORE
返回一个sv_does_sv
,指示boolean
是否执行特定的命名角色。SV
可以是Perl对象或Perl类的名称。
SV
我可以在implementation of universal.c
中看到对bool sv_does_sv(SV* sv, SV* namesv, U32 flags)
的呼叫。 SV角色的定义是什么?在哪里可以找到更多有关此的信息?
从用户级别看,这里的代码是做什么的(这是一个子引用)
sv_does_sv
在相同的调用中,返回的地址与UNIVERSAL->can('DOES')
不同,因此它做的事情有所不同,我可以在上面链接的UNIVERSAL->can('isa')
中看到该地址。
答案 0 :(得分:6)
UNIVERSAL::DOES
等效于:
sub DOES {
croak "Usage: invocant->DOES(kind)"
if @_ != 2;
$_[0]->isa($_[1]);
}
内部,sv_does_sv
在传递的第一个SV上调用isa
方法。 perl本身不提供角色的实现,因此由角色模块提供DOES
来解决这些问题。
Moose,Moo,Role :: Tiny,Mouse等中的约定是DOES
方法对于类及其父类以及该类及其父类组成的角色适用。这些库还提供了does
方法,该方法仅对类及其父类的组合角色有效,而对于类或其父类则不适用。