【问题标题】:Why does the toString method on scala.Function1 and scala.Function2 have parenthesis为什么scala.Function1和scala.Function2上的toString方法有括号
【发布时间】:2014-09-04 01:54:01
【问题描述】:

我正在实现(Int) => String) 的派生并覆盖toString 方法,如下所示:

object A extends ((Int) => String) {
  override def toString: String = "A"
  def apply(int: Int): String = int.toString
}

IDEA IntelliJ 表示 toString 方法被 Function1.toString 覆盖(Scala IDE 也是如此)。并且 IntelliJ 还显示以下警告,表明必须将空括号添加到 toString 方法,因为 Function1.toString 声明包括空括号(Scala IDE 不显示此警告):

空括号 Scala 方法被重写为无参数

惯例是,如果方法有边,则包含括号 效果。根据 Liskov 替换原理,如 覆盖方法是空括号,覆盖方法也必须是 声明为具有副作用的方法。 * 参考编程 Scala,5.3 运算符是方法

然后我去了 ScalaDoc 并检查了 scala 包中的 Function1 (source)、Function2 (source) 和 PartialFunction (source)。在 2.11.2 的源代码中,Function1Function2 都覆盖了 toString 方法并包含空括号(而 PartialFunction 只是使用 Function1 的覆盖)。所以,鉴于Function1Function2 都为toString 方法声明了String 文字,我不明白为什么括号会包含在这两个类文件的源代码中。

我遗漏了什么明显的东西来证明在 toString 方法上使用括号是合理的?还是 IntelliJ 警告不正确?或者如果 IntelliJ 警告是正确的,为什么 Scala IDE 没有显示与 IntelliJ 相同的警告?

【问题讨论】:

    标签: function scala tostring scala-ide intellij-13


    【解决方案1】:

    根据规范,override def f 覆盖 def f() 被假定具有括号。

    您引用的 IntelliJ 消息说有一个“约定”,您应该包含括号以记录该方法不仅是访问器,而且可能具有副作用。

    并非所有人都同意或遵守该符号“约定”。

    对于toString,约定尤其空洞,因为许多toString 方法具有副作用,例如迭代器初始化状态。

    我最近在 ML 上问过这个问题:

    https://groups.google.com/d/msg/scala-internals/ahNPTB6-P3M/1pPyptaH6coJ

    我在后续回答中回答了我自己的问题:

    http://www.scala-lang.org/files/archive/spec/2.11/05-classes-and-objects.html#overriding
    

    一个特殊的规则涉及无参数方法。 ... f 也被假定为 有一个空的参数列表。

    这意味着您可以将括号从覆盖定义中移除。

    例如,

    scala> def f = 42
    f: Int
    
    scala> f()
    <console>:9: error: Int does not take parameters
                  f()
                   ^
    
    scala> class X { def f() = 42 }
    defined class X
    
    scala> class Y extends X { override def f = 43 }
    defined class Y
    
    scala> new Y().f()
    res1: Int = 43
    

    Y.f 的参数列表为空。

    由于Object.toString() 有一个空参数列表,因此每个覆盖也是如此,包括Any.toString 的覆盖。

    (Java 的 toString() 被引用为提供括号的原因,在称为“空应用程序”的转换中。)

    【讨论】:

    • Tysvm 用于回答。我已经读了三遍你的答案,还读了谷歌线程。我仍然无法自信地得出结论。那么,这是简短的答案吗?重写 toString 方法时不需要括号,这意味着 IntelliJ 的警告不正确。如果是这样,如果您可以将其(或用您自己的话)作为摘要(或 tl;dr)放在顶部,我会接受您的回答,以便未来的读者可以快速得出结论而无需深入阅读。如果没有,那么请帮助我理解我最后一段中三个问题的答案。
    • 如果答案是括号可以省略,你知道他们为什么不省略 scala.Function1 和 scala.Function2 (特别是因为它们被分配了一个字符串文字)?
    • 我用了更强的词。
    猜你喜欢
    • 2022-11-10
    • 2014-04-18
    • 2016-06-26
    • 1970-01-01
    • 1970-01-01
    • 2021-05-12
    • 2018-07-28
    • 2014-09-30
    相关资源
    最近更新 更多