如何为Perl中的单命名参数对实现多分派(或替代方案)?
问题解决:Perl 6 多分派中命名参数匹配错误的修正
你的代码问题出在多分派的签名定义上,导致两次调用都匹配到了近战伤害的方法。以下是原因分析和修正方案:
问题根源
- 原
proto方法(Int :$)定义了匿名的Int类型命名参数,这会让所有带单个Int命名参数的调用都进入同一分派逻辑。 - 两个
multi方法的参数未指定类型(:$melee默认是Any类型),Perl 6会优先匹配第一个能兼容传入参数类型的方法,因此:3fire也会匹配到:$melee的分支。
修正后的代码
class Creature { has $.health = 10; has $.fire-resist; # 通用proto,接受任意参数列表,交由多分派系统匹配 proto method damage (|) { * } multi method damage (:Int() $melee) { say "Damaging in melee for $melee points"; $!health -= $melee; } multi method damage (:Int() $fire) { return if $!fire-resist; say "Damaging with fire for $fire points"; $!health -= $fire; } } # 测试 my Creature $creature .= new(:fire-resist); $creature.damage: :3melee; # 输出:Damaging in melee for 3 points $creature.damage: :3fire; # 因火抗无输出 say $creature.health; # 输出:7 my Creature $no-resist .= new; $no-resist.damage: :3fire; # 输出:Damaging with fire for 3 points say $no-resist.health; # 输出:7
关键修正点
- 给每个
multi方法的命名参数明确指定类型(:Int() $melee),让多分派系统能通过参数名+类型准确区分分支。 - 使用
proto method damage (|) { * }作为通用原型,它不限制参数列表结构,完全交由多分派逻辑处理匹配。
你也可以选择在proto中明确列出可能的参数(同样能解决问题):
proto method damage (:$melee, :$fire) { * }
内容的提问来源于stack exchange,提问作者Dmitry Matveyev
相关产品推荐
相关产品推荐

