:Cell
为什么sam1无法覆盖receive方法? scalac将两个特征编译为相同的代码。
// ok
val sam0: MySamWithEmptyParameter = () => 100
// doesn't work
// val sam1: MySamWithParameterless = () => 100
trait MySamWithEmptyParameter {
def receive(): Int
}
trait MySamWithParameterless {
def receive: Int
}
答案 0 :(得分:4)
SI-10555正是在谈论这个问题。这是一个简单的设计决策,只支持一个显式的空参数列表,即使这两个编译为一个空的参数列表无论如何。
The relevant part of the Specification says(强调我的):
- 方法m 必须有一个参数列表;
这确实有点尴尬,因为eta扩展适用于带有空参数列表的方法。
联系Lightbend的人。以下是Scala团队负责人Adrian Moors的回复:
最初的原因是保持规范简单,但也许我们应该重新审视。我同意令人惊讶的是它适用于
def a(): Int
,但不适用于您的示例。在内部,完全没有定义参数列表的方法和那些(甚至是空的)方法的处理方式不同。 这导致了之前的混淆/错误 - 仅举一例:https://github.com/scala/scala-dev/issues/284。
在2.13中,我们正在重新进行eta扩展(它将更积极地应用,但是 - ) - 插入将首先发生)。我们一直都是这样,但目前的想法是:
- 0-ary方法被特别处理:如果期望的类型是sam-等效于Function0,我们eta-expand;否则,插入
()
(在dotty中,你需要显式地写(),除非方法是java定义的) - 我仍然不确定我们是否应该在这里进行eta-expand- 对于所有其他arities,方法引用是eta扩展的,无论期望的类型如何(如果没有类型不匹配,这可能会在重构参数的方法时隐藏错误,但忘记在任何地方应用它们。但是,从那以后函数是一等值,通过简化参考方法值来构造它们很容易。)
结果是我们可以弃用方法值语法(
m _
),因为它只是简单地编写m
。 (请注意,这与占位符语法不同,如m(, _)
中所示。) (另请参阅此评论的主题:https://github.com/lampepfl/dotty/issues/2570#issuecomment-306202339)