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

Scala中如何让Entity特质的withId返回子类对应的IdAnd类型?

问题解决方法

问题根源在于Animal直接继承Entity[Animal],导致Cat实例的withId方法继承自Animal的定义,返回类型被固定为IdAnd[Animal],而非具体子类Cat对应的IdAnd[Cat]。以下是两种可行的修改方案:

方案一:让父特质支持子类自绑定泛型

// Generic trait to represent a class with its own type of ID
trait Entity[T <: Entity[T]] {
  self: T =>
  type ID

  final def withId(id: T#ID): IdAnd[T] = IdAnd(id, self)
}

case class IdAnd[T <: Entity[T]](id: T#ID, entity: T)

// 将Animal改为泛型特质,要求子类传入自身类型作为参数
sealed trait Animal[A <: Animal[A]] extends Entity[A] {
  override type ID = Long
}

// Cat继承时指定自身为泛型参数
case class Cat(name: String) extends Animal[Cat]

object Animal {
  val test: IdAnd[Cat] = Cat("Garfield").withId(1L) // 现在可正常编译
}

通过让Animal成为泛型特质,强制子类在继承时绑定自身类型,Entity的泛型参数T会被解析为具体子类(如Cat),withId方法的返回类型也就对应为IdAnd[Cat]。

方案二:使用this.type指代具体实例类型

trait Entity {
  type ID
  final def withId(id: ID): IdAnd[this.type] = IdAnd(id, this)
}

// 调整IdAnd的泛型约束,兼容任意Entity子类
case class IdAnd[T <: Entity](id: T#ID, entity: T)

sealed trait Animal extends Entity {
  override type ID = Long
}

case class Cat(name: String) extends Animal

object Animal {
  val test: IdAnd[Cat] = Cat("Garfield").withId(1L) // 编译正常
}

该方案移除了Entity的F-bounded泛型,改用this.type直接指代当前实例的具体类型,同时放宽IdAnd的泛型约束,使其能接受任意Entity子类。这样Cat实例调用withId时,返回类型会自动匹配为IdAnd[Cat]。

内容的提问来源于stack exchange,提问作者Maxence Cramet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 11:16:28