Scala隐式语境下“比...更具体”的判定规则具体是什么含义?
问题解答:Scala隐式优先级的判定差异
这不是编译器运行机制难以捉摸,核心原因是你对隐式声明「更具体」的判定规则理解存在偏差:返回值的子类型关系并不在所有场景下都能让隐式候选获得更高优先级,隐式方法和隐式函数值的判定逻辑存在本质区别。
你认知正确的基础场景(第一段代码)
class A class B extends A implicit val A = new A implicit val B = new B implicitly[A]
这段代码运行正常符合规则:寻找A类型的隐式值时,B的类型B是A的子类型,属于更具体的隐式候选,因此被优先选中,不会有歧义。
第二段代码编译失败的原因
implicit class会被编译器自动展开为同名的隐式方法,你的代码等价于:
class A(val toInt :Int) { def ! = (1 /: (2 to toInt))(_ * _) } class B(i :Int) extends A(i) implicit def A(toInt: Int): A = new A(toInt) implicit def B(i: Int): B = new B(i) 1.!
Scala对**隐式方法(包括implicit class生成的)**的具体性判定,只看参数列表的匹配度,完全不考虑返回值类型。这里两个隐式方法的参数都是单Int类型,参数列表完全一致,编译器会认为二者优先级相同,找不到更具体的候选,因此报歧义错误。
第三段代码编译成功的原因
第三段的隐式候选是两个Function1类型的隐式值:
class A(val toInt :Int) { def ! = (1 /: (2 to toInt))(_ * _) } class B(i :Int) extends A(i) implicit val A: Int => A = { i :Int => new A(i) } implicit val B: Int => B = { i :Int => new B(i) } 1.!
Scala的函数类型是协变的,签名为Function1[-T, +R],其中返回值类型参数R是协变的,因此Int => B是Int => A的子类型。此时两个候选是隐式值而非隐式方法,隐式值的具体性判定直接看类型的子类型关系,B的类型是目标转换类型的子类型,属于更具体的候选,因此被优先选中,不会出现歧义。
内容的提问来源于stack exchange,提问作者Turin
相关产品推荐
相关产品推荐

