Почему в этом коде есть неоднозначная ссылка на перегруженное определение? - PullRequest
0 голосов
/ 03 мая 2018

Почему в этом коде есть неоднозначная ссылка на перегруженное определение?

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)

Код выше дает ошибку компиляции:

неоднозначная ссылка на перегруженное определение,

[ошибка], оба метода m в классе B типа (a: A, o2: Any) B

[ошибка] и метод m в классе A типа (a1: A, a2: A) A [error] совпадают типы аргументов (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

Любые подсказки приветствуются.

1 Ответ

0 голосов
/ 03 мая 2018

Вы совершенно правы - версия 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, которая лучше соответствует вашим требованиям, но я вижу, что вы явно вызываете m для B (не A ) поэтому я не знаю, какой из них выбрать сейчас - лучше пометьте это, в противном случае, если я просто выберу один, вы можете не получить результаты, которые вы получили во время выполнения. "

...