【问题标题】:How does '20 seconds' work in Scala?Scala 中的“20 秒”是如何工作的?
【发布时间】:2013-02-12 19:32:21
【问题描述】:

以下如何编译:

import scala.concurrent.duration._

val time = 20 seconds

这里到底发生了什么?

【问题讨论】:

    标签: scala duration


    【解决方案1】:

    发生了一些事情。

    首先,Scala 允许在许多方法调用中省略点和括号,因此20 seconds 等价于20.seconds()*。

    其次,应用“隐式转换”。由于20Int 并且Int 没有seconds 方法,因此编译器会搜索采用Int 并返回确实有 seconds 的隐式转换方法,搜索受方法调用范围的限制。

    您已将DurationInt 导入您的作用域。由于DurationInt 是一个带有Int 参数的隐式类,它的构造函数定义了一个隐式Int => DurationInt 转换。 DurationInt 有一个 seconds 方法,因此它满足所有搜索条件。因此,编译器将您的调用重写为new DurationInt(20).seconds**。

    *我的意思是松散的。 20.seconds() 实际上是无效的,因为seconds 方法没有参数列表,因此在方法调用中必须省略括号

    **实际上,这并不完全正确,因为DurationInt 是一个值类,因此编译器会尽可能避免包装整数。

    【讨论】:

    • 任何足够先进的技术都与魔法无异。
    • 幸运的是,大多数 IDE 都能够区分它!隐式转换在 Scala 中被大量使用。如果您只是阅读文本文件,可能会令人困惑(“该方法从何而来”),但借助适当的工具支持,您应该能够找到自己的方法,此时 Scala 可以非常有意义且简洁。 (例如,20.seconds 比 new DurationInt(20).seconds() 更易读,只要你知道它是如何做到的)
    • 如果你发现自己使用了隐式,总是问问自己是否有办法在没有他们帮助的情况下实现同样的事情。 twitter.github.com/effectivescala/#Types 和泛型隐含
    • 其实seconds方法是不带括号定义的,所以带括号调用是错误的。
    • @Frank 说得好。我并不是要建议您可以在 Scala 中编写 20.seconds(),只是编译器正在以这种方式翻译调用。值得指出的是,如果对应的方法没有参数列表,则 Scala 要求省略括号,如本例所示。
    【解决方案2】:

    那里发生的“魔法”称为“隐式转换”。您正在导入隐式转换,其中一些处理 Int(和 Double)到 Duration 之间的转换。这就是你正在处理的问题。

    【讨论】:

    • 知道为什么导入 import scala.concurrent.duration._ 会解析 20 seconds 但实际上导入 DurationConversions 特征却没有? 编辑:刚刚意识到他们实际导入的是DurationInt。我猜这是因为您无法导入实际的特征?只有 Trait 的具体实现?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-04
    • 1970-01-01
    相关资源
    最近更新 更多