UNIVERSAL中“角色”的定义是什么,Perl角色如何工作?

时间:2019-09-16 14:37:12

标签: perl roles universal

Perl有一个内部的伪模块,称为UNIVERSAL,所有模块都从该伪模块继承。它有一个来自the docs on UNIVERSAL的名为DOES的方法。

  

$obj->DOES( ROLE )

     

CLASS->DOES( ROLE )

     

DOES检查对象或类是否扮演角色ROLE。角色是特定行为的命名组(通常是特定名称和签名的方法),类似于类,但本身不一定是完整的类。例如,日志记录或序列化可能是角色。

     

DOESisa相似,因为如果二者均为真,则您知道调用该方法的对象或类可以执行特定的行为。但是,DOESisa的不同之处在于,它并不关心被调用方如何执行操作,而只是在乎。 (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')中看到该地址。

1 个答案:

答案 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方法,该方法仅对类及其父类的组合角色有效,而对于类或其父类则不适用。