当未明确给出返回类型时,为什么可以用返回 String 的方法覆盖返回 Unit 的方法?

Sha*_*nil 11 overriding scala traits

我正在研究 Scala Edition1 https://www.artima.com/pins1ed/traits.html编程中的特征一章中的代码示例

由于我的错字,遇到了一个奇怪的行为。尽管覆盖方法的返回类型UnitString. 但是在对象上调用该方法时,它返回 Unit 但不打印任何内容。

trait Philosophical {
    def philosophize = println("I consume memory, therefore I am!")
}

class Frog extends Philosophical {
  override def toString = "green"
  override def philosophize = "It aint easy to be " + toString + "!"
}

val frog = new Frog
//frog: Frog = green

frog.philosophize
// no message printed on console

val f = frog.philosophize
//f: Unit = ()
Run Code Online (Sandbox Code Playgroud)

但是当我在重写的方法中给出显式返回类型时,它给出了一个编译错误:

class Frog extends Philosophical {
  override def toString = "green"
  override def philosophize: String = "It aint easy to be " + toString + "!"
}
         override def philosophize: String = "It aint easy to be " + toString +
                      ^
On line 3: error: incompatible type in overriding
       def philosophize: Unit (defined in trait Philosophical);
        found   : => String
        required: => Unit
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮助解释为什么在第一种情况下没有编译错误。

Ale*_*nov 8

当预期类型为 时Unit可以接受任何值

价值丢弃

如果e具有某种值类型并且预期类型为Unite则通过将其嵌入项中将其转换为预期类型{ e; () }


Thi*_*ilo 6

我的问题是为什么它在第一种情况下通过编译器

当您没有明确指定返回类型时,它是由它工作所需的类型推断出来的override

原来是这样Unit

由于String值(构成函数体的表达式的值)可以分配给Unit,编译器很高兴。

  • 您可以将返回类型缩小为子类型;但您不能将其缩小到只能隐式转换为重写方法的返回类型的类型。“String”到“Unit”更像是第二个,即使它不完全是那样。 (2认同)
  • 在字节码级别上也没有缩小返回类型,“Frog”中实际上有两个方法:“def philosophize : Integer”和“def philosophize : Number”。第二个实际上覆盖了“Philosophical”的方法(并调用第一个)。当然可以对“void”/其他任何东西做同样的事情,设计师只是决定不这样做。 (2认同)
  • 1.Java也是如此。2. 是的,在字节码中可以。参见例如/sf/ask/1305887901/和/sf/ask/4064597631/接口合成方法生成同时缩小返回类型。 (2认同)