04 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.

应该说类与类型是不一样的,类的英文为 class, 而类型的英文为 type.
虽然在 Perl6 中类和角色(role)通常表现得与类并无不同。可以说 Perl6 中的类型/Type 由类/class, 角色/role, 和子类型/subtype 组成。
通常我们通过子类(subclass)来继承类并添加一些新的属性或方法(增加能力),而我们将通过子类型来限制一些特性(可理解为去掉能力)。

最简单的比如我们要一个只能是偶数的子类型。我们就可以这么定义:

subtype EvenNum of Num where { $^n % 2 == 0 }
首先它继承了类型 Num 然后通过 where 来限定它为偶数($^n 为前面讲过的占位符参数)。
my EvenNum $n;
$n = 2;             # Okay
$n = -2;            # Okay
$n = 0;             # Okay
$n = 3;             # 出错
另一个例子:
subtype Str_not2b of Str where /^[isnt|arent|amnot|aint]$/;
                                                                            
my Str_not2b $hamlet;
$hamlet = 'isnt';   # Okay because 'isnt' ~~ /^[isnt|arent|amnot|aint]$/
$hamlet = 'amnt';   # Bzzzzzzzt!   'amnt' !~ /^[isnt|arent|amnot|aint]$/

detailed

  • 通常定义子类型的方法:
    my subtype Str_not2b of Str where /^[isnt|arent|amnot|aint]$/;
    # or
    my Str subtype Str_not2b where /^[isnt|arent|amnot|aint]$/;
  • 匿名的子类型定义为:
    Str where /^[isnt|arent|amnot|aint]$/;
    由此可以看出子类型定义的关键字不是 subtype 而是 where. where 在此的作用大致可以写为:
    { $_.does(Str) and $_ ~~ /^[isnt|arent|amnot|aint]$/; }
  • 子类型最主要用于限制参数类型。比如某子程序只接受奇数作为参数:
    sub check_even (Num where { $^n % 2 == 0 } $even) {...}
    如果觉得这样看起来很不顺,有很英语化的写法:
    sub check_even ($even of Num where { $^n % 2 == 0 }) {...}
  • 子类型最主要的作用为多种分派(multiple dispatch)的参数提供类型限制。
    multi sub mesg ($mesg of Str where /<profanity>/ is copy) { ... }
    
    multi sub mesg (($mesg of Num where { $^n % 2 == 0 }) { ... }
    
    multi sub mesg ($mesg of Str) { ... }
    默认带有限制子类型的 sub 比不带的优先级要高。也就是如果匹配 rule <profanity> 的话就调用该 sub, 都不匹配才调用不带限制的 sub


blog comments powered by Disqus