【问题标题】:Scala implicit usage choicesScala 隐式使用选择
【发布时间】:2010-11-27 03:42:22
【问题描述】:

我一直在想 transparent implicit 转换是否真的是一个好主意,以及是否实际上更多地使用隐式会更好,嗯,显式。例如,假设我有一个接受Date 作为参数的方法,并且我有一个隐式转换,它将String 转换为Date

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

private def foo(d: Date)

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

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)

这样做的好处是以后可以更清楚地了解正在发生的事情 - 我现在已经被透明的 implicit 转换所吸引了几次,我应该知道(OptionIterable 任何人?)和这种用法仍然允许我们利用implicits 的强大功能。

【问题讨论】:

    标签: scala implicit


    【解决方案1】:

    我相信,在可读性方面,进行隐式转换的更“显式”的方式比完全透明的方式要好得多,至少在这个例子中是这样。

    在我看来,从A 类型到B 类型完全透明地使用implicits 是可以的,因为您可以始终查看A 类型的对象,因为它能够在需要 B 类型的对象时使用。例如,StringRandomAccessSeq[Char] 的隐式转换总是有意义的 - 从概念上讲,String 总是可以被视为字符序列(在 C 中,字符串 只是 一个字符序列,例如)。对x.foreach(println) 的调用对all Strings 有意义。

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

    【讨论】:

      【解决方案2】:

      当您进行从 X 到 Y 的隐式转换(如上面从 String 到 Date 的转换)时,您实质上是在说,如果您一开始就可以完全控制 X 的编写,您就会实现 X或者是 Y 的子类。

      如果 X 实现 Y 有意义,则添加转换。如果没有,那可能是不合适的。例如,String 实现 RandomAccessSeq[Char] 是有意义的,但 String 实现 Date 可能没有意义(尽管 String 实现 StringDate 似乎很好)。

      (我来晚了,Flaviu 有一个很好的答案,但我想补充一下我对隐式的看法。)

      【讨论】:

        猜你喜欢
        • 2021-04-15
        • 2018-03-29
        • 2020-12-08
        • 2010-12-21
        • 2019-12-24
        • 1970-01-01
        • 2023-03-05
        • 2013-07-01
        • 1970-01-01
        相关资源
        最近更新 更多