Avoid implicit conversions like the plague they are.
Implicit conversions allow the compiler to treat values of a type as values of another type.
There’s at least one set of scenarios in which this is unambiguously bad: non-total conversions. That is, converting an A
to a B
when there exists A
s for which this conversion is impossible.
implicit def str2int(str: String): Int = Integer.parseInt(str)
What this does is give the compiler a proof, as far as it’s concerned, that all String
s are Int
s and he can accept the former where the later is expected.
Our proof is unfortunately flawed, and will result in runtime failures:
"foobar" / 2
// java.lang.NumberFormatException: For input string: "foobar"
// at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
// at java.lang.Integer.parseInt(Integer.java:580)
// at java.lang.Integer.parseInt(Integer.java:615)
// at repl.Session$App$.str2int(implicit_conversions.md:8)
// at repl.Session$App$$anonfun$1.apply$mcI$sp(implicit_conversions.md:15)
// at repl.Session$App$$anonfun$1.apply(implicit_conversions.md:15)
// at repl.Session$App$$anonfun$1.apply(implicit_conversions.md:15)
Total conversions are more palatable - they shouldn’t result in runtime failures, at least.
One common scenario is adding methods to an existing type:
implicit class ExtendedInt(i: Int) {
def add1: Int = i + 1
}
Which lets us run:
1.add1
// res0: Int = 2
In this scenario, all Int
s can be converted to ExtendedInt
: the conversion is total and cannot result in runtime failure.
Linter | Rule |
---|---|
WartRemover |