如何使用 mixin 实现 F-bounded 多态性?

How to achieve F-bounded poly-morphism with a mixin?

假设我有一个 mixin 特征,我想在其中定义一个方法,其 return 类型取决于特征混合到的对象的最终类型...

trait MultiUnit extends Quantity {
  this: Order =>

  def split(unmatchedQuantity: Long): (???, ???)

}

...例如,如果我有一个案例 class 混合在 MultiUnit 中,我希望 return 类型看起来如下...

case class MultiUnitLimitOrder(price: Double, quantity: Long) extends Order with MultiUnit {

  def split(unmatchedQuantity: Long): (MultiUnitLimitOrder, MultiUnitLimitOrder) = ???

}

...如果可能的话,我更喜欢使用类型成员而不是类型参数的解决方案。

如果 MultiUnit 的上限足够,您可以:

trait Order
trait Quantity

trait MultiUnit extends Quantity {
  this: Order =>
  type T <: MultiUnit

  def split(unmatchedQuantity: Long): (T, T)
}

case class MultiUnitLimitOrder(price: Double, quantity: Long) 
  extends Order with MultiUnit {
    override type T = MultiUnitLimitOrder
    override def split(unmatchedQuantity: Long): (MultiUnitLimitOrder, MultiUnitLimitOrder) = ???
}

我不会像您上面建议的那样使用抽象类型成员,f bounded 是正确的方法。如果您事先不知道 T 的类型,则该类型成员模式很有用,例如,您正在计算一个类型。当您请求隐式证据时,Shapeless 一直使用该模式,例如:

def test[Computed]()(implicit gen: Generic.Aux[Source, Computed]): Result[Computed] = {}

这个用来"transfer"Generic里面的一个内部类型成员的值class到Computed,上面的一个类型参数。

对于你的情况,除非你绝对必须,否则请保持简单。

trait Order
trait Quantity

trait MultiUnit[T <: MultiUnit[T]] extends Quantity {
  this: Order =>

  def split(unmatchedQuantity: Long): (T, T)
}

case class MultiUnitLimitOrder(price: Double, quantity: Long) 
  extends Order with MultiUnit[MultiUnitLimitOrder] {
    override def split(unmatchedQuantity: Long): (MultiUnitLimitOrder, MultiUnitLimitOrder) = ???
}

我也不明白为什么你需要一个 self-type 绑定到 this: Order 而不是简单的 with Order.