You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现OrderedPoint后用SortedSet触发“diverging implicit expansion”错误求助

解决SortedSet与OrderedPoint的隐式展开错误问题

我来帮你搞定这个问题——你碰到的"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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:35:25