实现OrderedPoint后用SortedSet触发“diverging implicit expansion”错误求助
我来帮你搞定这个问题——你碰到的"diverging implicit expansion"错误,本质是Scala的SortedSet需要一个适配OrderedPoint的Ordering隐式实例,但你的类定义里混入的Ordered[Point]没法直接满足这个需求,咱们分两种方案解决:
方案1:调整Ordered的类型参数为OrderedPoint
最直接的修复方式是让OrderedPoint混入Ordered[OrderedPoint]而非Ordered[Point]。这样Ordered特质自带的隐式转换就能生成SortedSet需要的Ordering[OrderedPoint]实例,代码修改如下:
package sfti.ch10 import java.awt.Point import scala.math.Ordered class OrderedPoint(x: Int, y: Int) extends Point(x, y) with Ordered[OrderedPoint] { override def compare(that: OrderedPoint): Int = { if (this.x != that.x) this.x - that.x else this.y - that.y } }
这么改之后,SortedSet[OrderedPoint]就能自动识别到正确的Ordering,因为Ordered[A]特质里有个内置的隐式方法toOrdering,当A是Ordered[A]的子类时,会自动生成Ordering[A]。
方案2:手动提供Ordering[OrderedPoint]隐式实例
如果你需要保持Ordered[Point]的继承关系(比如要和其他Point子类兼容),可以手动定义一个Ordering[OrderedPoint]的隐式实例,放在伴生对象里就行:
package sfti.ch10 import java.awt.Point import scala.math.{Ordered, Ordering} class OrderedPoint(x: Int, y: Int) extends Point(x, y) with Ordered[Point] { override def compare(that: Point): Int = { if (this.x != that.x) this.x - that.x else this.y - that.y } } object OrderedPoint { // 两种写法任选其一: // 写法1:利用元组的字典序排序 implicit val ordering: Ordering[OrderedPoint] = Ordering.by(p => (p.x, p.y)) // 写法2:复用已实现的compare方法 // implicit val ordering: Ordering[OrderedPoint] = (a: OrderedPoint, b: OrderedPoint) => a.compare(b) }
这样在创建SortedSet[OrderedPoint]时,Scala会自动找到这个隐式实例,不会再出现展开错误。
为什么原来的写法会出错?
简单来说,SortedSet[OrderedPoint]需要的是Ordering[OrderedPoint],但你原来的OrderedPoint混入的是Ordered[Point],它只能提供Ordering[Point]。虽然OrderedPoint是Point的子类,但Ordering是逆变的,Scala没法自动把Ordering[Point]转换成Ordering[OrderedPoint],这就导致隐式解析过程陷入循环,最终抛出"diverging implicit expansion"错误。
内容的提问来源于stack exchange,提问作者Bob Kuhar

