使用Proxy时,存储方法是否可以使用多调度?在下面的最小示例中,存储Int
时会调用代码
my $foo := do {
my $bar = 1;
Proxy.new:
:FETCH( method { return $bar} ),
:STORE( method (Int $i) { $bar = $i } )
}
say $foo; # 1
$foo = 2;
say $foo; # 2
$foo = "3"; # error, need to pass an Int
但是如果给定一个Str
,我想以不同的方式处理STORE
。我发现的工作(除了使用给定
/的巨型方法之外,
是在块内创建一个multisub
,并返回sub(因为multimethod
不能用引用
my $foo := do {
my $bar = 1;
Proxy.new:
:FETCH( method { return $bar} ),
:STORE(
do {
multi sub xyzzy ($, Int $i) { $bar = $i }
multi sub xyzzy ($, Str $i) { $bar = +$i + 1}
&xyzzy
}
)
}
say $foo; # 1
$foo = 2;
say $foo; # 2
$foo = "3";
say $foo; # 4
有没有更好的方法来做到这一点(主要是为了使用方法
的代码清晰,因为sub
感觉…误导)?
关于误导:FETCH
和STORE
值预期Callables
,它可以是方法
或子
。
回到问题,没有直接的方法可以做到这一点,但有一个更好的间接方法可能更清晰。您可以通过首先设置multisub
,然后将proto
作为参数传递来做到这一点:
proto sub store(|) {*}
multi sub store(\self, Int) { say "Int" }
multi sub store(\self, Str) { say "Str" }
my $a := Proxy.new(
FETCH => -> $ { 42 },
STORE => &store,
);
say $a; # 42
$a = 42; # Int
$a = "foo"; # Str
如果你想让代码更短,但可能不太容易理解,你可以去掉proto
(因为它会为你自动生成)和多
中的sub
(因为你可以):
multi store(\self, Int) { say "Int" }
multi store(\self, Str) { say "Str" }
my $a := Proxy.new(
FETCH => -> $ { 42 },
STORE => &store,
);
say $a; # 42
$a = 42; # Int
$a = "foo"; # Str