如何利用Raku OO特性消除集成层样板代码
实现方案1:闭包回调(完全符合你预期的调用方式)
你的思路是完全可行的,修正伪代码的小问题后可直接运行:
class Error { has Real $.absolute; has Callable:D &!get-value is required; method percent { "{ ($!absolute / &!get-value()).abs * 100 }%" } } class Measure { has Real $.value; has Error $.error; method new(:$value, :$error) { my $error_obj = Error.new( absolute => $error, get-value => { self.value } ); self.bless(:$value, :$error($error_obj)); } } my $m = Measure.new(value => 10, error => 1); say $m.error.percent; # 输出 10%
优势:Error内部所有需要用到测量值的方法都可以直接获取最新的Measure.value,就算后续把$.value改为可写属性,也不会出现数据不一致的问题,完全符合你想要的调用形式。
实现方案2:方法代理(Raku原生特性,更少样板代码)
如果你不介意直接在Measure实例上调用方法,可以用Raku的handles特性自动代理方法,不需要修改Error类,也不用写中间方法:
class Error { has Real $.absolute; method percent( $value ) { "{ ( $!absolute / $value ).abs * 100 }%" } } class Measure { has Real $.value; has Error $.error handles(:percent(&.error.percent: $.value)); method new( :$value, :$error ) { self.bless( :$value, error => Error.new( absolute => $error ) ) } } my $m = Measure.new( value => 10, error => 1 ); say $m.percent; # 输出 10%
优势:保持了Error类的独立性,不需要额外引入回调属性,Error类可以脱离Measure单独复用,更符合关注点分离的设计原则。
方案取舍
- 如果必须要
$m.error.percent的调用形式,选方案1即可 - 如果更看重类的复用性和低耦合,你原来的传参方案、或者方案2都是更稳妥的选择,仅多一行中间方法的成本很低,换来的可维护性收益更高
内容的提问来源于stack exchange,提问作者librasteve
相关产品推荐
相关产品推荐

