gpt4 book ai didi

java - Scala 重载不选择最具体的方法

转载 作者:行者123 更新时间:2023-12-01 18:23:31 25 4
gpt4 key购买 nike

拥有 Java 类:

class abstract Exp
class ExpAdd extends Exp
class ExpSub extends Exp

和 Scala 方法:

def interpret(e: ExpAdd) = interpret(e.left_arg) + interpret(e.right_arg)
def interpret(e: ExpSub) = interpret(e.left_arg) - interpret(e.right_arg)

def interpret(exp: Exp) = exp match {
case e : ExpAdd = interpret(e)
case e : ExpSub = interpret(e)
}

如何重构代码以使更容易添加新的Exps?我认为解释(Exp)根本不会被使用,因为另外两个更具体并且

If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.

但是 Scala 中的情况似乎并非如此。我也尝试删除解释(Exp)但编译器不喜欢它。这就是为什么我使用 case 子句......有什么方法可以使重载按预期工作吗?或者也许有一些解决方法?

最佳答案

正如 @Alexy 所说,方法解析基于参数的编译时或“静态”类型。您可以使操作数的类型成为表达式类型的一部分,然后使用隐式为给定类型递归构造解释器:

trait Exp
case class ExpAdd[A <: Exp, B <: Exp](left_arg: A, right_arg: B) extends Exp
case class ExpSub[A <: Exp, B <: Exp](left_arg: A, right_arg: B) extends Exp
case class Literal(i: Int) extends Exp

trait ExpInterpreter[E <: Exp] {
def interpret(e: E): Int
}
object ExpInterpreter {
implicit object LiteralInterpreter extends Interpreter[Literal] {
def interpret(l: Literal) = l.i
}
implicit def addInterpreter[A <: Exp, B <: Exp](
implicit leftInterpreter: Interpreter[A], rightInterpreter: Interpreter[B]) =
new Interpreter[ExpAdd[A, B]] {
def interpret(e: ExpAdd[A, B]) = leftInterpreter.interpret(e.left_arg) +
rightInterpreter.interpret(e.right_arg)
}
implicit def subInterpreter ...
}

然后当您添加新的 Exp 时在这种情况下,您只需要定义一个新的隐式,并且可以在任何地方执行此操作,而不必将情况添加到特定的匹配表达式中。你甚至可以有 ExpExpInterpreter在一个库中,案例和特定解释器在不同的 jar 中。

正如所写,这意味着表达式的结构是其类型的一部分(并且您必须携带该类型直到您解释它 - 无法解释泛型 Exp ,只能解释 E <: Exp: ExpInterpreter ),但是也许可以使用与 Free monad 类似的技术克服这个问题?

关于java - Scala 重载不选择最具体的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26957154/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com