Scala toString:括号还是不括号?

inc*_*ate 21 scala

我喜欢这个帖子是某种优点/缺点的总结,用于覆盖和调用toString有或没有空括号,因为这件事有时让我感到困惑,即使我已经进入Scala很长一段时间了.

那么哪一个优于另一个?Scala极客,官员和OCD偏执狂的评论受到高度赞赏.

优点toString:

  • 乍一看似乎是一个明显而自然的选择;
  • 大多数情况都是微不足道的,只是在不改变内部状态的情况下即时构建字符串;
  • 另一种常见的情况是将方法调用委托给包装的抽象:

    override def toString = underlying.toString
    
    Run Code Online (Sandbox Code Playgroud)

优点toString():

  • 绝对不是"类似访问者"的名称(这就是IntelliJ IDEA检查员每隔一段时间就会抱怨一次);
  • 可能意味着某些CPU或I/O工作(在计算每个System.arrayCopy调用对性能至关重要的情况下);
  • 甚至可能意味着一些可变的状态改变(考虑一个例子,当第一次toString调用是昂贵的,所以它在内部缓存以便在将来产生更快的调用).

那么最佳做法是什么?我还缺少什么吗?

更新:这个问题与toString每个JVM对象上定义的具体相关,所以我希望找到最佳实践,如果它存在的话.

Lui*_*hys 22

这是Scala中的编程(第10.3节)必须说的:

建议的约定是在没有参数时使用无参数方法,并且该方法仅通过读取包含对象的字段来访问可变状态(特别是,它不会改变可变状态).此约定支持统一访问原则,1表示客户端代码不应受到将属性实现为字段或方法的决定的影响.

这是(非官方的)斯卡拉风格指南(第18页)必须说的:

Scala允许在arity-0(无参数)方法上省略括号:

reply() 
// is the same as 
reply 
Run Code Online (Sandbox Code Playgroud)

但是,只有在相关方法没有副作用(纯功能)时才应使用此语法.换句话说,在调用queue.size时省略括号是可以接受的,但在调用println()时则不行.该约定反映了上面给出的方法声明约定.

后者没有提到统一访问原则.

如果您的toString方法可以实现为a val,则意味着该字段是不可变的.但是,如果您的类是可变的,则toString可能并不总是产生相同的结果(例如StringBuffer).所以在Scala中编程意味着我们应该toString()在两种不同的情况下使用:

1)当它的值是可变的

2)有副作用时

就个人而言,我认为忽略其中的第一个是更常见和更一致的.在实践中toString几乎从不会产生副作用.所以(除非它确实如此),总是使用toString并忽略统一访问原则(遵循样式指南):保留括号以表示副作用,而不是可变性.


Lan*_*dei 9

是的,你遗漏了一些东西:语义学.

如果你有一个只返回一个值的方法,你就不应该使用parens.原因是这模糊了vals和defs 之间的界限,满足了统一访问原则.例如,考虑size收集的方法.对于固定大小的矢量或数组,这可能只是一个val,其他集合可能需要计算它.

空白parens的使用应限于执行某种副作用println()的方法,例如,增加内部计数器的方法,或重置连接等的方法.