为什么在此代码中对重载定义有不明确的引用?
class A {
def m(a1: A, o2: Any): A = {
print("1")
a1
}
def m(a1: A, a2: A): A = {
print("2")
a1
}
def m(o1: Any, o2: Any): Any = {
print("3")
o1
}
def m(o: Any): Any = {
print("4")
o
}
}
class B extends A {
def m(b1: B, o2: Any): A = {
print("5")
b1
}
override def m(a: A, o2: Any): B = {
print("6")
this
}
override def m(o1: Any, o2: Any): Any = {
print("7")
o1
}
def m(i: Int): Unit = { print("8") }
}
val a = new A
val b = new B
b.m(a, a)
上面的代码给出了编译错误:
对重载定义的模糊引用,
[error]类型B中的方法m(a:A,o2:Any)B
[error]和类型A中的方法m(a1:A,a2:A)A [错误]匹配 参数类型(A,B)
但我的理解是method m in class A of type (a1: A, a2: A)A
更具体
比method m in class B of type (a: A, o2: Any)B
任何提示都表示赞赏。
答案 0 :(得分:1)
您完全正确 - m
中A
的版本更具体,实际上是问题所在。
由于您实际在m
的实例(即b
)上调用b.m(a, a)
,编译器首先检查是否存在与B
中的签名匹配的方法。由于B
确实有一个方法可以通过类型检查(即m(a: A, o2: Any): B
)到目前为止这么好。但是,虽然编译器还会检查超类A
,但它会找到更具体的m
版本(即m(a1: A, a2: A): A
)。
问题是您在m
的实例上调用了B
,但是您明确要求编译器找到一个带有两个A
类型参数的方法。编译器现在不确定您实际打算执行哪个版本,因此编译错误。
更好的编译信息可能是:
“嘿,我在m
的层次结构中找到了A
的更高版本,更符合您的要求,但我发现您在{{1}上明确调用了m
(不是B
)所以我真的不知道现在选择哪一个 - 如果我只选择一个你可能无法得到你在运行时获得的结果,你最好检查一下。“