Scala隐式使用选择

oxb*_*kes 23 scala implicit

我一直想知道透明 implicit转换是否真的是一个好主意,是否真的可以更好地使用implicits更多,嗯,明确.例如,假设我有一个接受a Date作为参数的方法,并且我有一个隐式转换,它将a String转换为Date:

implicit def str2date(s: String) : Date = new SimpleDateFormat("yyyyMMdd").parse(s)

private def foo(d: Date)
Run Code Online (Sandbox Code Playgroud)

那显然我可以通过透明implicit转换来调用它:

foo("20090910")
Run Code Online (Sandbox Code Playgroud)

将字符串转换为更明确的日期这一事实会更好吗?

class DateString(val s: String) { 
  def toDate : Date = new SimpleDateFormat("yyyyMMdd").parse(s) 
}

implicit def str2datestr(s: String) : DateString = new DateString(s)
Run Code Online (Sandbox Code Playgroud)

那么用法看起来更像是:

foo("20090910".toDate)
Run Code Online (Sandbox Code Playgroud)

这样做的好处是稍后会发生什么事情更清楚 - 我现在已经被implicit我应该知道的透明转换(OptionIterable任何人?)已经被抓了几次,这种用法仍然允许我们利用implicit秒.

Fla*_*gan 44

我认为,在可读性方面,更明确的"隐式转换"方式要比完全透明的方式好得多,至少在本例中是这样.

在我看来,当你总是可以查看类型的对象时,只要需要类型的对象,就可以implicit完全透明地使用类型A到类型.例如,a 到a 的隐式转换总是有意义的 - 概念上,它总是可以被视为一个字符序列(例如,在C中,字符串只是一个字符序列).呼吁对所有人都有意义.BABStringRandomAccessSeq[Char]Stringx.foreach(println) String

在另一方面,当类型的对象,应使用的更明确的转化A可以有时被用作类型的对象B.在您的示例中,调用foo("bar")没有意义并抛出错误.由于Scala没有检查异常,因此调用foo(s.toDate)清楚地表明可能会抛出异常(s可能不是有效日期).此外,foo("bar".toDate)显然看起来不对,而你需要查阅文档,看看为什么foo("bar")可能是错的.Scala标准库中的一个例子是从Strings到Ints的转换,通过包装器的toInt方法RichString(Strings可以看作Ints,但不是所有时间).


Jor*_*tiz 13

当你从X到Y进行隐式转换时(比如从上面的String到Date的转换),你基本上是这样说的,如果你已经完全控制了X的编写,那么你就可以制作X工具或者是Y的子类.

如果X实现Y是有意义的,那么添加转换.如果没有,那么可能不合适.例如,String实现RandomAccessSeq [Char]是有意义的,但也许String没有意义实现Date(尽管String实现StringDate似乎没问题).

(我有点晚了,Flaviu有一个很好的答案,但我想补充一下关于我如何看待隐含的评论.)