已弃用:自动应用
以前,在调用没有参数的空参数方法时,会隐式插入一个空参数列表 ()
。示例
def next(): T = ...
next // is expanded to next()
在 Scala 3 中,这种用法是错误的。
next
^
missing arguments for method next
在 Scala 3 中,应用语法必须完全遵循参数语法。此规则的例外是定义在 Java 中或覆盖定义在 Java 中的方法。对这些方法更宽松的原因是,否则每个人都必须编写
xs.toString().length()
而不是
xs.toString.length
后者是 Scala 中的惯用写法,因为它符合 *统一访问原则*。该原则指出,应该能够将对象成员从字段更改为无副作用的方法,反之亦然,而不会影响访问该成员的客户端。因此,Scala 鼓励定义此类“属性”方法,而不带 ()
参数列表,而副作用方法应使用它定义。在 Java 中定义的方法无法进行这种区分;对它们来说,()
始终是强制性的。因此,Scala 通过允许无参数引用来解决客户端问题。但是,Scala 允许对所有方法引用进行这种自由,而 Scala 3 将其限制为对未在 Scala 3 中定义的外部方法的引用。
出于向后兼容性的原因,Scala 3 目前也为在 Scala 2 中定义的或覆盖在 Scala 2 中定义的方法的空参数方法自动插入 ()
。事实证明,由于到目前为止在 Scala 中没有强制执行定义和调用之间的对应关系,因此在 Scala 2 库中存在相当多的方法定义以不一致的方式使用 ()
。例如,我们在 scala.math.Numeric
中发现
def toInt(): Int
而 toInt
在其他地方都写成没有参数。对引用此类方法强制执行严格的参数对应关系会将不一致性投射到客户端代码,这是不可取的。因此,Scala 3 在类型检查对这些方法的引用时选择更宽松,直到大多数 Scala 2 中的核心库得到清理。
更严格的符合规则也适用于覆盖空参数方法。不再允许用空参数方法覆盖无参数方法,反之亦然。相反,两种方法必须在参数列表中完全一致。
class A:
def next(): Int
class B extends A:
def next: Int // overriding error: incompatible type
覆盖 Java 或 Scala 2 方法的方法再次免除此要求。
迁移代码
在 -source 3.0-migration
下,具有不一致参数的现有 Scala 代码仍然可以在 Scala 3 中编译。当与 -rewrite
选项配对时,代码将被自动重写以符合 Scala 3 的更严格检查。
参考
有关更多信息,请参阅 Issue #2570 和 PR #2716。