Как достичь F-ограниченного полиморфизма с помощью миксина?


Предположим, что у меня есть черта mixin, где я хочу определить метод, возвращаемый тип которого зависит от конечного типа объекта, в который эта черта смешивается...

trait MultiUnit extends Quantity {
  this: Order =>

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

}

...например, если у меня есть класс case, который смешивается в MultiUnit , я бы хотел, чтобы возвращаемый тип выглядел следующим образом...

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

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

}

...Я бы предпочел решение, которое использует члены типа вместо параметров типа, если это возможно.

2 2

2 ответа:

Я бы не стал использовать абстрактный член типа, как вы предлагаете выше, f bounded-это правильный путь. Этот шаблон элементов типа полезен, если вы заранее не знаете тип T, например, вы вычисляете тип. Бесформенный использует этот шаблон все время, когда вы требуете неявных доказательств, таких как:

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

Это используется для "переноса" значения внутреннего члена типа внутри класса Generic в 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.

Если верхняя граница на 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) = ???
}