我有一个这样的班级:
class Foo {
method some-method(Str $name) { ... }
}
简单用法:
my $foo = Foo.new;
$foo.some-method("peter");
由于“某些方法”会被频繁调用,因此我想做一些事情让用户使用它,如下所示:
$foo.peter;
我知道FALLBACK可以完成这项工作,但是它已用于另一种方法。 我试图定义一个中缀运算符:
sub infix:<%>(Foo $foo, $name) {
$foo.some-method($name);
}
下面的代码有效,但是双引号很烦人。
$foo % "peter";
那么有什么办法可以避免引号?还是任何简化调用的方法?
答案 0 :(得分:8)
正如Curt Tilmes所指出的那样,您可以将Foo
对象用作Associative
(或Hash
):
class Foo {
method some-method(Str $name) { ... }
method AT-KEY(Str $name) { self.some-method($name) }
}
my $foo = Foo.new;
say $foo<peter>; # same as $foo.some-method("peter")
当然,AT-KEY
方法可以是多种方法,因此您也可以使用它来进行各种技巧。
class Foo {
method some-method(Str $name) { "$name is ok" }
multi method AT-KEY("peter") { "peter is special" }
multi method AT-KEY(Str $name) { self.some-method($name) }
}
my $foo = Foo.new;
say $foo<peter>; # "peter is special"
say $foo<joe>; # "joe is ok"
答案 1 :(得分:6)
有一种方法可以使用FALLBACK
进行多个操作,只要它们有所不同。
通过检查对象的某些属性:
class Foo {
# this could be set as part of `new`/`BUILD`
has %!special = ( "peter" => 42 );
multi method FALLBACK ( $name where (%!special{$name}:exists) ) {
%!special{$name}
}
multi method FALLBACK ( $other ) {
$other.tc
}
}
with Foo.new {
say .paul; # Paul
say .peter; # 42
}
这有一个潜在的远距离动作的问题。
具有不同数量或类型的参数:
class Bar {
multi method FALLBACK ( Str:D $name ) {
$name.tc
}
multi method FALLBACK ( Str:D $name, Real:D $number ) {
$name.tc, 1 / $number
}
multi method FALLBACK ( Str:D $name, Str:D $other ) {
$name.tc, $other.uc
}
}
with Bar.new {
say .paul; # Paul
say .peter(42); # Peter, 0.02381
say .peter('Paul'); # Peter, PAUL
}
您可以将.[…]
用作Int参数。
class Baz {
method AT-POS ( $arg ) { say "Baz[$arg]" }
}
Baz.new[42,32]; # Baz[42]
# Baz[32]
内置的postcircumfix:« [ ] »
将参数强制转换为Int,但是您可以在组合中添加一个新参数。
(这样做有很多注意事项。)
multi sub postcircumfix:<[ ]> ( Baz:D $b, $a ) is export {
# $b.AT-POS( $a )
$b.some-method( $a )
}
您可以将.<…>
用于空格分隔的Strs,或将.{…}
用于任意值。
class Other {
multi method AT-KEY ( Str:D $name ){
$name.tc
}
multi method AT-KEY ( Real:D $number ){
1 / $number
}
}
with Other.new {
say $_<peter>; # Peter
say $_.<paul>; # Paul
say .<peter paul>; # Peter Paul
# note that AT-Key got called twice
say $_{42,'peter'}; # 0.02381, Peter
# note that AT-Key got called twice
}
您可以使其成为可调用对象。
class Fubar {
multi method CALL-ME ( Str:D $name ){
$name.tc
}
multi method CALL-ME ( Real:D $number ){
1 / $number
}
multi method CALL-ME ( +@args ){
@args.map: {self.CALL-ME($_)}
}
}
with Fubar.new {
say $_('peter'); # Peter
say $_(42); # 0.02381
# this calls the +@args one
say $_('paul',32); # Paul, 0.03125
}
在执行任何这些操作之前,您应该真正考虑一下您的API。