Scala中隐含的低优先级和高优先级
low priority and high priority implicits in scala
在以下来自 Scala 的 puzzlers 的代码中,隐式似乎没有冲突,因为 TestAlarmHandler
更具体。虽然我不明白解释。为什么 TestAlarmHandler
比 DefaultAlarmHandler
更具体?
object Scanner {
trait Console { def display(item: String) }
trait AlarmHandler extends (() => Unit)
def scanItem(item: String)(implicit c: Console) {
c.display(item)
}
def hitAlarmButton()(implicit ah: AlarmHandler) { ah() }
}
class OperatingMode {
implicit val ConsoleRenderer = new Scanner.Console {
def display(item: String) { println(s"Found a ${item}") }
}
implicit val DefaultAlarmHandler = new Scanner.AlarmHandler {
def apply() { println("ALARM! ALARM!") }
}
}
object NormalMode extends OperatingMode
object TestMode extends OperatingMode {
override implicit val ConsoleRenderer = new Scanner.Console {
def display(item: String) { println("Found a detonator") }
}
implicit val TestAlarmHandler = new Scanner.AlarmHandler {
def apply() { println("Test successful. Well done!") }
}
}
import NormalMode._
scala> Scanner scanItem "knife"
Found a knife
scala> Scanner.hitAlarmButton()
ALARM! ALARM!
import TestMode._
scala> Scanner scanItem "shoe"
Found a detonator
scala> Scanner.hitAlarmButton()
Test successful. Well done!
那是因为 TestMode 是 OperationMode 的子类,scala 首先在 TestMode 的范围内查找隐式,只有在找不到时才会在层次结构中查找。
TestAlarmHandler
比 DefaultAlaramHandler
更具体,因为 TestAlarmHandler
是在匿名 class 中定义的,它派生自 class OperatingMode
定义DefaultAlarmHandler
.
形式上,the Scala Language Specification 指定了当找到多个符合条件的参数时如何处理的情况,如下所示(请注意,TestAlarmHandler
和 DefaultAlarmHandler
都符合条件,因为它们已被由 import TestMode._
导入):
If there are several eligible arguments which match the implicit parameter's type, a most specific one will be chosen using the rules of static overloading resolution.
第6.26.3 Overloading Resolution节根据相对权重的概念定义了更具体的概念:
The relative weight of an alternative A over an alternative B is a number from 0 to 2, defined as the sum of
- 1 if A is as specific as B, 0 otherwise, and
- 1 if A is defined in a class or object which is derived from the class or object defining B, 0 otherwise.
TestAlarmHandler
相对于DefaultAlarmHandler
的相对权重为1,而DefaultAlarmHandler
相对于TestAlarmHandler
的相对权重为0。注意TestAlarmHandler
定义在一个匿名 class 派生自 class OperatingMode
定义 DefaultAlarmHandler
。第一条规则在解决方法重载时很重要,但在这里不相关。
An alternative A is more specific than an alternative B if the relative weight of A over B is greater than the relative weight of B over A.
TestAlarmHandler
比 DefaultAlaramHandler
更具体,因为 TestAlarmHandler
相对于 DefaultAlarmHandler
的相对权重大于相反的权重。
在以下来自 Scala 的 puzzlers 的代码中,隐式似乎没有冲突,因为 TestAlarmHandler
更具体。虽然我不明白解释。为什么 TestAlarmHandler
比 DefaultAlarmHandler
更具体?
object Scanner {
trait Console { def display(item: String) }
trait AlarmHandler extends (() => Unit)
def scanItem(item: String)(implicit c: Console) {
c.display(item)
}
def hitAlarmButton()(implicit ah: AlarmHandler) { ah() }
}
class OperatingMode {
implicit val ConsoleRenderer = new Scanner.Console {
def display(item: String) { println(s"Found a ${item}") }
}
implicit val DefaultAlarmHandler = new Scanner.AlarmHandler {
def apply() { println("ALARM! ALARM!") }
}
}
object NormalMode extends OperatingMode
object TestMode extends OperatingMode {
override implicit val ConsoleRenderer = new Scanner.Console {
def display(item: String) { println("Found a detonator") }
}
implicit val TestAlarmHandler = new Scanner.AlarmHandler {
def apply() { println("Test successful. Well done!") }
}
}
import NormalMode._
scala> Scanner scanItem "knife"
Found a knife
scala> Scanner.hitAlarmButton()
ALARM! ALARM!
import TestMode._
scala> Scanner scanItem "shoe"
Found a detonator
scala> Scanner.hitAlarmButton()
Test successful. Well done!
那是因为 TestMode 是 OperationMode 的子类,scala 首先在 TestMode 的范围内查找隐式,只有在找不到时才会在层次结构中查找。
TestAlarmHandler
比 DefaultAlaramHandler
更具体,因为 TestAlarmHandler
是在匿名 class 中定义的,它派生自 class OperatingMode
定义DefaultAlarmHandler
.
形式上,the Scala Language Specification 指定了当找到多个符合条件的参数时如何处理的情况,如下所示(请注意,TestAlarmHandler
和 DefaultAlarmHandler
都符合条件,因为它们已被由 import TestMode._
导入):
If there are several eligible arguments which match the implicit parameter's type, a most specific one will be chosen using the rules of static overloading resolution.
第6.26.3 Overloading Resolution节根据相对权重的概念定义了更具体的概念:
The relative weight of an alternative A over an alternative B is a number from 0 to 2, defined as the sum of
- 1 if A is as specific as B, 0 otherwise, and
- 1 if A is defined in a class or object which is derived from the class or object defining B, 0 otherwise.
TestAlarmHandler
相对于DefaultAlarmHandler
的相对权重为1,而DefaultAlarmHandler
相对于TestAlarmHandler
的相对权重为0。注意TestAlarmHandler
定义在一个匿名 class 派生自 class OperatingMode
定义 DefaultAlarmHandler
。第一条规则在解决方法重载时很重要,但在这里不相关。
An alternative A is more specific than an alternative B if the relative weight of A over B is greater than the relative weight of B over A.
TestAlarmHandler
比 DefaultAlaramHandler
更具体,因为 TestAlarmHandler
相对于 DefaultAlarmHandler
的相对权重大于相反的权重。