Scala вывод типа при перегруженном методе

С учетом этого кода:

class Rational(n: Int, d: Int) {
  require(d != 0)
  private val g = gcd(n.abs, d.abs)
  val numerator = n / g
  val denominator = d / g

  def this(n: Int) = this(n, 1)

  override def toString = numerator + "/" + denominator

  def +(r: Rational) = new Rational(numerator * r.denominator + r.numerator * denominator, denominator * r.denominator)

  def *(r: Rational) = new Rational(numerator * r.numerator, denominator * r.denominator)

  def +(i: Int) = new Rational(i) + this

  private def gcd(a: Int, b: Int) : Int = {
    if (b == 0) a else gcd(b, a % b)
  }

}

Почему scala не может сделать вывод, что + (i: Int) возвращает Rational? (fsc дает ошибку overloaded method + needs result type)

если я изменил этот метод на:

def +(i: Int): Rational = { new Rational(i) + this }

Он работает...

Ответы

Ответ 1

Я нашел поток в списке рассылки scala с точно таким же вопросом здесь. Ответы там немного объясняют, почему требуется указать тип возврата. Изучив еще немного, я также нашел следующее: Когда тип возврата требуется для методов в Scala. Если я должен процитировать ответ оттуда:

Когда требуются аннотации явного типа.

В практическом плане вы должны предоставить явные аннотации типов для следующих ситуаций:

Возвращает значения метода в следующих случаях:

  • Когда вы явно вызываете return в методе (даже в конце).
  • Когда метод рекурсивный.
  • Когда метод перегружен и один из методов вызывает другой. Вызывающий метод требует аннотации типа возвращаемого значения.
  • Когда тип возвращаемого возврата будет более общим, чем вы предполагали, например, Any.

Ответ 2

В этом случае он может вывести правильный тип, но он просто недостаточно умен. Легко построить некоторые патологические примеры с перегруженными методами, когда ситуация становится очень запутанной, поэтому я думаю, что команда Scala решила сделать четкий разрез и потребовать тип возврата. Это похоже на рекурсивные методы, в которых вам нужен тип результата, даже если компилятор мог его вывести во многих случаях.