0
votes

Why there is ambiguous reference to overloaded definition in this code?

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)

The code above gives compile error:

ambiguous reference to overloaded definition,

[error] both method m in class B of type (a: A, o2: Any)B

[error] and method m in class A of type (a1: A, a2: A)A [error] match argument types (A, B)

But my understanding is that method m in class A of type (a1: A, a2: A)A is more specific than method m in class B of type (a: A, o2: Any)B

Any hints are appreciated.

1

1 Answers

1
votes

You are exactly right - the version of m in A is more specific and that is actually the problem.

Since you are actually invoking m on an instance of b (ie. b.m(a, a)) the compiler first checks that there is a method that matches the signature in B. Since B does indeed have a method that passes type checking (ie. m(a: A, o2: Any): B) so far so good. But whilst the compiler also checks the superclass A it finds a more specific version of m (ie. m(a1: A, a2: A): A).

The problem is you invoked m on an instance of B but you are explicitly asking the compiler to find a method that takes two arguments of type A. The compiler is now unsure of which version you actually intended to get executed hence the compilation error.

A better compilation message might be:

"Hey I found a version of m further up the hierarchy in A that better meets your requirements but I see you are explicitly invoking m on a B (not an A) so I don't really know which one to choose now - you better check this otherwise if I just choose one you may not get the results you were after at runtime."