Journal(2005) | Blog(2006) | RandomLink | WhoAmI | LiveBookmark | HomePage

<<Previous: $Perl6 = $class.bless(:Example<12>);  >>Next: Class::Date 的两个常见用途

role Example13 { # Perl6 }

Category: Perl6   Keywords: role Perl6

Intro.

role 是类代码的复用。有点类似模块可以将子程序导出到某一程序或另一模块,一个 role 能将它的属性和方法导出到另一个类。注意,它与继承不同。
很多语言都有这个功能:比如 Ruby 有 mixins, Java 有 interfaces, 和某些版本的 Smalltalk 有 traits. Perl6 的 role 比它们略好一点。

easy example

class Dog {
    does bark;
    ...
}
class Wolf does bark {
    ...
}
role bark {
    method barking {
        say 'Wooo!';
    }
}
my $dog = Dog.new();
$dog.barking(); # Wooo!
my $wolf = Wolf.new();
$wolf.barking(); # Wooo!
这就是 role, 一种没有什么继承关系的代码复用。:)
如果 role 里定义了私有方法,注意此方法不是对 role 是私有的,而是对使用的类。
role 里可以调用 role 也可以继承 class.最简单的讲 role 和 class 就是关键字不同。

mixins

如果在一个类后面加 does role 的话,那是在编译时就加进去了。
而在一个对象后面加 does role 的话,那是在运行时才加进去的。
# 上面的例子我们不在 class 后面或里面加  does bark
if $pet ~~ Dog|Wolf { $pet does bark; $pet.barking(); }

方法冲突

假设我们有 class Dog, role Pet 和 role Sentry. role 中都定义了方法 shake. 所以一般而言,碰到冲突的解决方案有:
  1. 在 class 中定义 shake 来覆盖。或者该 shake 方法通过指定不同调用不同 role 的方法。
  2. 用 multi 通过类型来避免冲突

property 和 but

如果你需要一个 role, 而这个 role 只有一个与它名字一样的属性的话,Perl6 中提供了关键字 property 来简化操作。
比如下面的代码就可以简化为一行:
my role answer {
    has int $.answer is rw;
}
 # 用 property 简化
my int property answer;
but 与 does 不同的是 but 在一个副本上作变动。
$a = 0 but answer(42);
# 等同于
$tmp = 0;  # $tmp 为 0 的一个副本
$tmp does answer; # answer 是前面定义的一个属性 role
$tmp.answer = 42;
$a = $tmp;
# 或者我们可以怎么写:
(($anonymous = 0) does answer).answer = 42;
$a = $anonymous;
这么定义后 $a 本身还是为 0, 只是它有一个 answer 属性。由于是 is rw 的,所以可以这么设置:
$a.answer = 44;
but 最大的用途是后面跟一个 Enum 枚举类型。Enum 稍后再说,或请参考 Perl6::Bible::A12Perl6::Bible::S12.

<<Previous: $Perl6 = $class.bless(:Example<12>);  >>Next: Class::Date 的两个常见用途

Options: +Del.icio.us

Related items Created on 2005-05-31 18:22:03, Last modified on 2005-06-04 18:36:56
Copyright 2004-2005 All Rights Reserved. Powered by Eplanet && Catalyst 5.62.