role Metamodel::Mixins {}

警告:此角色是 Rakudo 实现的一部分,不属于语言规范。

使用中缀运算符 doesbut,可以创建基本对象和任意数量的角色(或另一个对象)的混合类。这些是其类型具有两个操作数类型的属性的对象。分别地,这些重新将现有对象设置为具有生成的混合类类型,并使用所述混合类类型克隆所述对象

class Billboard {
    has Str:D $.advertisement is required;
 
    method vandalism(::?CLASS:D: --> Str:D{ ... }
 
    multi method Str(::?CLASS:D: --> Str:D{ $!advertisement }
 
    role Vandalized[Str:D :$vandalism{
        method vandalism(::?CLASS:D: --> Str:D{ $vandalism }
 
        multi method Str(::?CLASS:D: --> Str:D{ $vandalism }
    }
}
 
my Str:D $advertisement = Q:to/ADVERTISEMENT/.chomp; 
Brilliant Solutions: sane and knowledgeable consultants.
We have been providing excellent services since 1972!
ADVERTISEMENT
my Str:D $vandalism = Q:to/VANDALISM/.chomp; 
          S       s  s ne     k          l   o   l     .
We    e  ee            e  e  e    e    e      e     !
VANDALISM
 
my Billboard:D $billboard .= new: :$advertisement;
say $billboard eq $advertisement# OUTPUT: «True␤» 
 
my Billboard:D $draft = $billboard but Billboard::Vandalized[:$vandalism];
say $draft eq $vandalism# OUTPUT: «True␤» 
 
$billboard does Billboard::Vandalized[:$vandalism];
say $billboard eq $vandalism# OUTPUT: «True␤» 

混合类可以选择性地具有混合类属性。当只有一个角色只有一个公共属性混入对象时,就会发生这种情况。如果结果混合类的类型上存在混合类属性,则可以使用其 value 命名参数通过 butdoes 对其进行初始化。这使得混合类不仅可以具有可组合的方法,还可以具有可组合的状态。使用此功能,可以重写上面的示例,以便在无需生成更多混合类的情况下,可以多次破坏广告牌,方法是将 Billboard::Vandalism$vandalism 命名参数变为 rw 混合类属性

class Billboard {
    has Str:D $.advertisement is required;
 
    method vandalism(::?CLASS:D: --> Str:D{ ... }
 
    multi method Str(::?CLASS:D: --> Str:D{ $!advertisement }
 
    role Vandalized {
        has Str:D $.vandalism is required is rw;
 
        multi method Str(::?CLASS:D: --> Str:D{ $!vandalism }
    }
}
 
my Str:D $advertisement = Q:to/ADVERTISEMENT/.chomp; 
Brilliant Solutions: sane and knowledgeable consultants.
We have been providing excellent services since 1972!
ADVERTISEMENT
my Str:D $vandalism = Q:to/VANDALISM/.chomp; 
          S       s  s ne     k          l   o   l     .
We    e  ee            e  e  e    e    e      e     !
VANDALISM
my Str:D $false-alarm = Qs:to/FALSE-ALARM/.chomp;
$vandalism
⬆️ This is just one of our namesakes we at Brilliant Solutions have been
helping people like you create since 1972!
FALSE-ALARM
 
my Billboard:D $billboard .= new: :$advertisement;
say $billboard eq $advertisement# OUTPUT: «True␤» 
 
$billboard does Billboard::Vandalized :value($vandalism);
say $billboard eq $vandalism# OUTPUT: «True␤» 
 
$billboard.vandalism = $false-alarm;
say $billboard eq $false-alarm# OUTPUT: «True␤» 

Metamodel::Mixins 是实现所述混合类行为的元角色。形式上,混合类是其 HOW 从基本可组合元对象继承并应用任意数量的角色的对象,从而形成一个 HOW 具有其属性组合的对象。特别是,此元角色提供的元方法用于实现中缀运算符 butdoes 的行为,但这些方法还支持与混合类相关的内省。例如,当使用对象和一个角色调用 but 时所做的工作可以使用提供的 mixin 元方法显式编写

class Foo { }
role Bar { }
 
say Foo.new but Bar;     # OUTPUT: «Foo+{Bar}.new␤» 
say Foo.new.^mixin(Bar); # OUTPUT: «Foo+{Bar}.new␤» 

方法§

方法 set_is_mixin§

method set_is_mixin($obj)

$obj 标记为混合类。

方法 is_mixin§

method is_mixin($obj)

如果 $obj 已使用 set_is_mixin 标记为混合类,则返回 1,否则返回 0

方法 set_mixin_attribute§

method set_mixin_attribute($obj$attr)

$obj 的混合类属性设置为 $attr(应为 Attribute 实例)。

方法 mixin_attribute§

method mixin_attribute($obj)

返回使用 set_mixin_attribute 设置的 $obj 的混合类属性。

方法 setup_mixin_cache§

method setup_mixin_cache($obj)

$obj 设置混合类的缓存。在此元方法被调用后,对 mixin 的调用将不会为给定相同角色列表的 $obj 混合类创建新的类型。这应在合成之前某个时间点调用。

方法 flush_cache§

method flush_cache($obj)

无操作。

方法 generate_mixin§

method generate_mixin($obj@roles)

创建从 $obj 继承并执行 @roles 中每个角色的新混合元对象。然后对其进行组合,并在返回之前设置其混合属性(如果存在)。

虽然这会生成一个新的混合类型,但这并不会实际将其混合到 $obj 中;如果您打算这样做,请改用 mixin 元方法。

方法 mixin§

method mixin($obj*@roles:$needs-mixin-attribute)

通过使用 $obj@roles 调用 generate_mixin 来生成新的混合类型。如果 $obj 已组合,则事先检查 $obj 的混合缓存,以查找针对这些角色的任何现有混合。如果 $obj 是某个类型的实例,则这将返回使用生成的混合重新祝福的 $obj,否则这将返回混合本身。

如果 $needs-mixin-attributeTrue,则在返回之前,如果在生成的混合上不存在混合属性,这将引发异常。