题
我一直想知道透明 隐式
转换是否真的是一个好主意,是否真的可以更好地使用implicits more,嗯, 。例如,假设我有一个接受 Date
作为参数的方法,并且我有一个隐式转换,它将 String
转换为 Date
:
implicit def str2date(s: String) : Date = new SimpleDateFormat("yyyyMMdd").parse(s)
private def foo(d: Date)
然后显然我可以使用透明的隐式
转换来调用它:
foo("20090910")
最好是将字符串转换为更明确的日期吗?
class DateString(val s: String) {
def toDate : Date = new SimpleDateFormat("yyyyMMdd").parse(s)
}
implicit def str2datestr(s: String) : DateString = new DateString(s)
那么用法看起来更像是:
foo("20090910".toDate)
这样做的好处是稍后会发生什么事情更清楚 - 我现在已经被我应该了解的透明隐式
转换了几次( Option 代码>到
Iterable
任何人?)这个用法仍然允许我们利用隐式
的强大功能。
解决方案
我相信更“明确”的至少在本例中,隐式转换的方式在可读性方面要比完全透明方式好得多。
在我看来,当你总是>时,从 A
到 B
完全透明地使用隐式
是可以的em>查看 A
类型的对象,因为只要需要 B
类型的对象就可以使用它。例如, String
隐式转换为 RandomAccessSeq [Char]
总是有意义的 - 从概念上讲, String
总是可以被视为一系列字符(例如,在C中,字符串只是一系列字符)。对 x.foreach(println)
的调用对于所有 String
是有意义的。
另一方面,当 A
类型的对象有时可以用作 B类型的对象时,应该使用更明确的转换代码>。在您的示例中,对
foo(" bar")
的调用没有意义并且会引发错误。由于Scala没有检查异常,因此对 foo(s.toDate)
的调用清楚地表明可能会抛出异常( s
可能不是有效日期)。此外, foo(“bar”.toDate)
显然看起来不对,而您需要查阅文档以了解为什么 foo(" bar")
可能出错。 Scala标准库中的一个示例是 String
s到 Int
的转换,通过 RichString <的
toInt
方法/ code> wrapper( String
s可以看作是 Int
s,但不是所有)。
其他提示
当你进行从X到Y的隐式转换时(比如从上面的String到Date的转换),你基本上是这样说的,如果你首先完全控制了写X,那么你就可以使用X实现或者是Y的子类。
如果X实现Y是有意义的,那么添加转换。如果没有,那么可能不合适。例如,String实现RandomAccessSeq [Char]是有意义的,但是对于String实现Date可能没有意义(尽管实现StringDate的String看起来很好)。
(我有点晚了,Flaviu有一个很好的答案,但我想补充一下关于我如何看待implicits的评论。)