02 June 2005
This post may be outdated due to it was written on 2005. The links may be broken. The code may be not working anymore. Leave comments if needed.

Delegation

Delegation, 中文的意思可以为代表,授权或是委托。
Delegation 能让你在一个 class 或 role 里把另一个对象的方法当成自己的。

例子用于理解

class Dog {
    method wag { 2 }
    method run { 100 }
}
class Wolf {
    method wag { 4 }
}
class Snoopy {
    has $.tail handles 'wag';
}
my $pet = Snoopy.new;
# $pet.wag; 错误,不知道 $.tail 对应哪个类
$pet.tail = Dog.new; # 这里的 $pet 没有继承 Dog 类
$pet.wag; # 2
$pet.tail = Wolf.new; # 将 $.tail 对应到 Wolf
$pet.wag; # 4, $.tail 对应 Wolf, 所以调用 Wolf.wag;

其中最关键的一句就是 has $.tail handles 'wag'; 它使类 Snoopy 产生了一个方法 wag. 而调用 wag 就等同于调用 $.tail.wag 所以这话也就等同于在类里定义了如下代码:

method wag (*@args is context(Lazy)) { $.tail.wag(*@args) }
关键字 handles 的中文意思可以为处理。所以代码 has $.tail handles 'wag' 的字面意思理解可以为“用 $.tail 来处理 wag 调用”。

方法多样化

  • 如果要多于一个方法的话,可以这么表示:
    has $.tail handles <wag run>;
  • 其实我们是用智能匹配来处理 handles 后面的参数。比如:
    has $:fur handles /^get_/;
    # 智能匹配正则表达式,所以以 get_ 开头的方法调用都委托 $:fur 对象来处理
    
    has $:fur handles Groomable;
    # handles 的方法就是 Groomable 里的所有方法
  • 如果你想定义一个方法名字而实际调用的是另一个方法,可以使用 Pair.
    has $:fur handles { :shakefur<shake> :scratch<get_fleas> };
    # 当你调用 shakefur 时实际上调用了 $:fur.shake
  • 可以更进一步,使用正则替换来改变方法名:
    has $:fur handles (s/^furget_/get_/);
    # 当你调用 furget_a 时实际调用的是 get_a

Want more?

See Synopsis12.


blog comments powered by Disqus