我一直想知道透明 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
我应该知道的透明转换(Option
对Iterable
任何人?)已经被抓了几次,这种用法仍然允许我们利用implicit
秒.
Fla*_*gan 44
我认为,在可读性方面,更明确的"隐式转换"方式要比完全透明的方式好得多,至少在本例中是这样.
在我看来,当你总是可以查看类型的对象时,只要需要类型的对象,就可以implicit
完全透明地使用类型A
到类型.例如,a 到a 的隐式转换总是有意义的 - 概念上,它总是可以被视为一个字符序列(例如,在C中,字符串只是一个字符序列).呼吁对所有人都有意义.B
A
B
String
RandomAccessSeq[Char]
String
x.foreach(println)
String
在另一方面,当类型的对象,应使用的更明确的转化A
可以有时被用作类型的对象B
.在您的示例中,调用foo("bar")
没有意义并抛出错误.由于Scala没有检查异常,因此调用foo(s.toDate)
清楚地表明可能会抛出异常(s
可能不是有效日期).此外,foo("bar".toDate)
显然看起来不对,而你需要查阅文档,看看为什么foo("bar")
可能是错的.Scala标准库中的一个例子是从String
s到Int
s的转换,通过包装器的toInt
方法RichString
(String
s可以看作Int
s,但不是所有时间).
Jor*_*tiz 13
当你从X到Y进行隐式转换时(比如从上面的String到Date的转换),你基本上是这样说的,如果你已经完全控制了X的编写,那么你就可以制作X工具或者是Y的子类.
如果X实现Y是有意义的,那么添加转换.如果没有,那么可能不合适.例如,String实现RandomAccessSeq [Char]是有意义的,但也许String没有意义实现Date(尽管String实现StringDate似乎没问题).
(我有点晚了,Flaviu有一个很好的答案,但我想补充一下关于我如何看待隐含的评论.)