我希望这个帖子能够覆盖和覆盖toString
有或没有空括号的优点/缺点,因为这件事有时让我感到困惑,即使我已经进入Scala很长一段时间。
那么哪一个优于另一个? Scala极客,官员和OCD偏执狂的评论受到高度赞赏。
toString
的优点:
另一个常见的情况是将方法调用委托给包装的抽象:
override def toString = underlying.toString
toString()
的优点:
System.arrayCopy
次呼叫计数对性能至关重要的情况下); toString
调用很昂贵时,所以它会在内部缓存,以便将来产生更快的调用。)那么最佳做法是什么?我还缺少什么吗?
更新:这个问题与每个JVM对象上定义的toString
具体相关,所以我希望找到最佳实践,如果它永远存在。
答案 0 :(得分:22)
这是 Scala编程(第10.3节)必须说的:
建议的惯例是每当使用无参数方法 没有参数,方法只能通过访问可变状态 读取包含对象的字段(特别是,它没有 改变可变状态)。此约定支持统一访问 原则,1表示客户端代码不应受到a的影响 决定将属性实现为字段或方法。
这是(非官方的) Scala风格指南(第18页)必须说的:
Scala允许省略arity-0方法的括号(no 争论):
reply()
// is the same as
reply
然而,这种语法 只应在有问题的方法没有副作用时使用 (纯功能性)。换句话说,省略是可以接受的 调用queue.size时调用括号,但调用println()时不调用括号。 该约定反映了上面给出的方法声明约定。
后者没有提到统一访问原则。
如果您的toString
方法可以实现为val
,则表示该字段是不可变的。但是,如果您的班级是可变的,toString
可能并不会总是产生相同的结果(例如StringBuffer
)。所以 Scala编程意味着我们应该在两个不同的情况下使用toString()
:
1)当其值可变时
2)有副作用时
就我个人而言,我认为忽略其中的第一个是更常见和更一致的。在实践中,toString
几乎不会产生副作用。所以(除非它),总是使用toString
并忽略统一访问原则(遵循样式指南):保留括号以表示副作用,而不是可变性。
答案 1 :(得分:9)
是的,你遗漏了一些东西:语义。
如果你有一个只返回一个值的方法,你就不应该使用parens。原因是这会使val
和def
之间的界线模糊,满足Uniform Access Principle。例如。考虑集合的size
方法。对于固定大小的向量或数组,这可能只是val
,其他集合可能需要计算它。
空的parens的使用应限于执行某种副作用的方法,例如, println()
,或增加内部计数器的方法,或重置连接等的方法。
答案 2 :(得分:3)
我建议始终使用toString
。关于你对toString()
的第三个“专家”:
可能意味着一些可变状态发生变化(考虑一个例子,当第一次toString调用很昂贵时,所以它在内部缓存以便将来产生更快的调用。)
首先,toString
通常不应该是一项昂贵的操作。但是假设它很昂贵,并且假设您确实选择在内部缓存结果。即使在这种情况下,我也会说使用toString
,只要toString
的结果对于给定的对象状态总是相同的(无论状态如何) toString
缓存)。
我不推荐使用toString
没有parens的唯一原因是你有一个代码分析器/分析器根据是否存在parens进行假设。在这种情况下,请遵循所述分析器提出的约定。另外,如果您的toString
那么复杂,请考虑将其重命名为其他内容,例如expensiveToString
。非正式地预期toString
在大多数情况下是一个简单明了的函数。
答案 3 :(得分:2)
在这个答案中没有多少论证,但仅GenTraversableOnce
声明了以下没有括号的defs:
toArray
toBuffer
toIndexedSeq
toIterable
toIterator
toList
toMap
toSeq
toSet
toStream
toTraversable