Category: Perl6 Keywords: subtype perl6
应该说类与类型是不一样的,类的英文为 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)的参数提供类型限制。
默认带有限制子类型的 sub 比不带的优先级要高。也就是如果匹配 rulemulti 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) { ... }<profanity>的话就调用该 sub, 都不匹配才调用不带限制的 sub