我在类中有一个方法来返回哈希值,目的是让子类覆盖该方法。但出于测试目的,我想要一个不同的哈希值。当类被实例化时,我希望测试选项被假定为 False,因此:test在不需要时可以省略。
目前我这样做:
class A {
has %.tmps;
submethod BUILD( :$test = False ) {
%!tmps = $test ?? self.test-tmps !! self.default-tmps
}
method test-tmps { ... }
method default-tmps { ... }
}
Run Code Online (Sandbox Code Playgroud)
这就是我想要的,调用my A $x .= newdefault-tmps,并my A $y .=new(:test)调用test-tmps。
但我想知道如何通过多重调度删除 $test 的显式检查。但我无法找出适当的语法。我试过
class A {
has %.tmps;
submethod BUILD( :$test = False ) {
%!tmps = self.get-tmps( :$test )
}
multi method get-tmps( :test($)! where * ) {
# return the hash for test values
}
multi method get-tmps( :test($)! where ! * ) {
# return the hash for default values
}
}
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为我总是得到测试值,无论我是否:test在 中指定new。所以我的问题是:
如何仅根据布尔值选择多方法候选者?
如果我想做的事情是可能的,是否有理由(例如运行时/编译时检查)为什么BUILD由 调用的显式签入会new比多重调度候选选择更好?
然后,如果多重调度有效,那么以下内容是否有效,或者$!test因为其%.tmps构建时间未定义而为 False?
class A {
has Bool $!test;
has %.tmps = self.get-tmps( :$!test );
submethod BUILD( :$!test = False ) {}
multi method get-tmps( :test($)! where * ) { ... }
# replacing the following by whatever is the correct syntax
multi method get-tmps( :test($) where ! * ) { ... }
}
Run Code Online (Sandbox Code Playgroud)
首先,现在我更推荐使用TWEAK方法,而不是BUILD方法。TWEAK 语义一般更偏向 DWIM。
TWEAK其次,该方法(或BUILD方法,就此而言)没有什么特别的。所以他们可以multi!
这让我想到了以下解决方案:
class A {
has %.temps;
multi submethod TWEAK(--> Nil) {
%!temps = a => 42;
}
multi submethod TWEAK(:$test! --> Nil) {
$test
?? (%!temps = a => 666) # testing
!! self.TWEAK(|%_); # NOT testing
}
}
say A.new(:test).temps; # {a => 666}
say A.new(:!test).temps; # {a => 42}
say A.new.temps; # {a => 42}
Run Code Online (Sandbox Code Playgroud)
请注意!在:$test!. 这使得命名参数成为强制性的。test因此,只要指定命名参数,就会选择该候选者。但这也包括用False值指定的情况,如 中所示:!test。这就是为什么需要在该候选人身上进行测试。
另请注意%_中的self.TWEAK(|%_). Raku 中的所有方法都定义了隐式 *%_(slurpy hash)参数。因此,您可以%_在方法内部使用来指示未由显式命名参数捕获的所有参数(例如:$test在本例中)。所以基本上是在没有self.TWEAK(|%_)所有显式命名参数的情况下重新调度。
最后:--> Nil仅仅表明该方法不会返回值。这可能允许编译器生成更有效的字节码。
| 归档时间: |
|
| 查看次数: |
152 次 |
| 最近记录: |