I'd like this thread to be some kind of summary of pros/cons for overriding and calling toString
with or without empty parentheses, because this thing still confuses me sometimes, even though I've been into Scala for quite a while.
So which one is preferable over another? Comments from Scala geeks, officials and OCD paranoids are highly appreciated.
Pros to toString
:
another common case is to delegate method call to the wrapped abstraction:
override def toString = underlying.toString
Pros to toString()
:
System.arrayCopy
call is crucial to performance);toString
call is expensive, so it is cached internally to yield quicker calls in future).So what's the best practice? Am I still missing something?
Update: this question is related specifically to toString
which is defined on every JVM object, so I was hoping to find the best practice, if it ever exists.
Here's what Programming In Scala (section 10.3) has to say:
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.
Here's what the (unofficial) Scala Style Guide (page 18) has to say:
Scala allows the omission of parentheses on methods of arity-0 (no arguments):
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.
The latter does not mention the Uniform Access Principle.
If your toString
method can be implemented as a val
, it implies the field is immutable. If, however, your class is mutable, toString
might not always yield the same result (e.g. for StringBuffer
). So Programming In Scala implies that we should use toString()
in two different situations:
1) When its value is mutable
2) When there are side-effects
Personally I think it's more common and more consistent to ignore the first of these. In practice toString
will almost never have side-effects. So (unless it does), always use toString
and ignore the Uniform Access Principle (following the Style Guide): keep parentheses to denote side-effects, rather than mutability.
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 val
s and def
s, satisfying the Uniform Access Principle. E.g. consider the size
method for collections. For fixed-sized vectors or arrays this can be just a val
, other collections may need to calculate it.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With