我一直想知道透明 隐式转换是否真的是一个好主意,是否真的可以更好地使用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(&quot; bar&quot;)的调用没有意义并且会引发错误。由于Scala没有检查异常,因此对 foo(s.toDate)的调用清楚地表明可能会抛出异常( s 可能不是有效日期)。此外, foo(“bar”.toDate)显然看起来不对,而您需要查阅文档以了解为什么 foo(&quot; bar&quot;)可能出错。 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的评论。)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top