Scala toString:括号与否?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8124055/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:39:47  来源:igfitidea点击:

Scala toString: parenthesize or not?

scala

提问by incarnate

I'd like this thread to be some kind of summary of pros/cons for overriding and calling toStringwith or without empty parentheses, because this thing still confuses me sometimes, even though I've been into Scala for quite a while.

我希望这个线程是对toString使用或不使用空括号进行覆盖和调用的优缺点的某种总结,因为这件事有时仍然让我感到困惑,即使我已经使用 Scala 有一段时间了。

So which one is preferable over another? Comments from Scala geeks, officials and OCD paranoids are highly appreciated.

那么哪一个比另一个更可取呢?高度赞赏 Scala 极客、官员和强迫症偏执狂的评论。

Pros to toString:

优点toString

  • seems to be an obvious and natural choice at the first glance;
  • most cases are trivial and just construct Strings on the fly without ever modifying internal state;
  • another common case is to delegate method call to the wrapped abstraction:

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

    override def toString = underlying.toString
    

Pros to toString():

优点toString()

  • definitely not "accessor-like" name (that's how IntelliJ IDEA inspector complains every once in a while);
  • might imply some CPU or I/O work (in cases where counting every System.arrayCopycall is crucial to performance);
  • even might imply some mutable state changing (consider an example when first toStringcall is expensive, so it is cached internally to yield quicker calls in future).
  • 绝对不是“类似访问器”的名称(这就是 IntelliJ IDEA 检查员每隔一段时间抱怨的方式);
  • 可能意味着一些 CPU 或 I/O 工作(在计算每个System.arrayCopy调用对性能至关重要的情况下);
  • 甚至可能意味着一些可变的状态改变(考虑一个例子,当第一次toString调用很昂贵,所以它在内部缓存以在未来产生更快的调用)。

So what's the best practice? Am I still missing something?

那么最佳实践是什么?我还缺少什么吗?

Update: this question is related specifically to toStringwhich is defined on every JVM object, so I was hoping to find the best practice, if it ever exists.

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

回答by Luigi Plinge

Here's what Programming In Scala(section 10.3) has to say:

以下是Scala 编程(第 10.3 节)所说的:

The recommended convention is to use a parameterless method whenever there are no parameters and the method accesses mutable state only by reading fields of the containing object (in particular, it does not change mutable state). This convention supports the uniform access principle,1 which says that client code should not be affected by a decision to implement an attribute as a field or method.

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

Here's what the (unofficial) Scala Style Guide(page 18) has to say:

这是(非官方的)Scala 风格指南(第 18 页)所说的:

Scala allows the omission of parentheses on methods of arity-0 (no arguments):

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

reply() 
// is the same as 
reply 

However, this syntax should only be used when the method in question has no side-effects (purely-functional). In other words, it would be acceptable to omit parentheses when calling queue.size, but not when calling println(). This convention mirrors the method declaration convention given above.

但是,这种语法只应在所讨论的方法没有副作用(纯函数式)时使用。换句话说,在调用 queue.size 时省略括号是可以接受的,但在调用 println() 时则不能。这个约定反映了上面给出的方法声明约定。

The latter does not mention the Uniform Access Principle.

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

If your toStringmethod can be implemented as a val, it implies the field is immutable. If, however, your class is mutable, toStringmight not always yield the same result (e.g. for StringBuffer). So Programming In Scalaimplies that we should use toString()in twodifferent situations:

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

1) When its value is mutable

1) 当它的值是可变的

2) When there are side-effects

2) 当有副作用时

Personally I think it's more common and more consistent to ignore the first of these. In practice toStringwill almost never have side-effects. So (unless it does), always use toStringand ignore the Uniform Access Principle (following the Style Guide): keep parentheses to denote side-effects, rather than mutability.

我个人认为忽略第一个更常见也更一致。在实践中toString几乎不会有副作用。因此(除非这样做),请始终使用toString并忽略统一访问原则(遵循样式指南):保留括号以表示副作用,而不是可变性。

回答by Landei

Yes, you are missing something: Semantics.

是的,你错过了一些东西:语义。

If you have a method that simply gives back a value, you shouldn't use parens. The reason is that this blurs the line between vals and defs, satisfying the Uniform Access Principle. E.g. consider the sizemethod for collections. For fixed-sized vectors or arrays this can be just a val, other collections may need to calculate it.

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

The usage of empty parens should be limited to methods which perform some kind of side effect, e.g. println(), or a method that increases an internal counter, or a method that resets a connection etc.

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

回答by Dan Burton

I would recommend always using toString. Regarding your third "pro" to toString():

我建议始终使用toString. 关于你的第三个“亲” toString()

Might imply some mutable state changing (consider an example when first toString call is expensive, so it is cached internally to yield quicker calls in future).

可能意味着一些可变状态改变(考虑一个例子,当第一次 toString 调用很昂贵,所以它在内部缓存以在未来产生更快的调用)。

First of all, toStringgenerally shouldn'tbe an expensive operation. But suppose it is expensive, and suppose you do choose to cache the result internally. Even in that case, I'd say use toString, as long as the resultof toStringis always the same for a given state of the object (disregarding the state of the toStringcache).

首先,toString通常不应该是一项昂贵的操作。但是假设它很昂贵,并且假设您确实选择在内部缓存结果。即使在这种情况下,我会说使用toString,只要结果toString始终是对象的给定状态的相同(不考虑状态toString缓存)。

The only reason I would not recommend using toStringwithout parens is if you have a code profiler/analyzer that makes assumptions based on the presence or absence of parens. In that case, follow the conventions set forth by said profiler. Also, if your toStringis that complicated, consider renaming it to something else, like expensiveToString. It is unofficially expected that toStringbe a straightforward, simple function in most cases.

我不建议在toString没有括号的情况下使用的唯一原因是,如果您有一个代码分析器/分析器,可以根据括号的存在与否做出假设。在这种情况下,请遵循所述分析器规定的约定。此外,如果您的toString内容如此复杂,请考虑将其重命名为其他名称,例如expensiveToString. toString在大多数情况下,非正式地认为这是一个直接、简单的函数。

回答by Debilski

Not much argumentation in this answer but GenTraversableOncealone declares the following defs without parentheses:

在这个答案中没有太多论证,但GenTraversableOnce单独声明了以下不带括号的定义:

toArray
toBuffer
toIndexedSeq
toIterable
toIterator
toList
toMap
toSeq
toSet
toStream
toTraversable