向下转换Scala中的类型类

时间:2017-12-02 18:58:16

标签: scala casting typeclass implicit downcast

我有

trait OptionTransaction {
  def data: Data
}

BuyOptionTransaction extends OptionTransaction
SellOptionTransaction extends OptionTransaction

我将这些用于Formatter类型类来创建各种事务的字符串表示

trait Formatter[T] {
  def format(ot:T):String
}

object Formatter {
  def apply[T](implicit screen: Formatter[T]) = screen

  implicit val buyOT = new Formatter[BuyOptionTransaction] {
    def format(ot: BuyOptionTransaction):String = ot.x.toString
  }

  implicit val sellOT = new Formatter[SellOptionTransaction] {
    def format(ot: SellOptionTransaction):String = ot.y.toString
  }
}

这是切入点:

import Formatter._
val closeTransactions: List[OptionTransaction] = ...
closeTransactions.map(startFormat)

问题closeTransactions类型为List[OptionTransaction],类型类需要OptionTransaction向下转换为BuyOptionTransactionSellOptionTransaction否则它不会找到隐式格式化程序。

如何自动实现这种向下投射?

2 个答案:

答案 0 :(得分:2)

如果要处理多态运行时,需要实现某种动态(运行时)调度而不是类型类,它们是静态的(编译时)。它看起来像这样:

type Data = String
trait OptionTransaction {
  def data: Data = ""
}

class BuyOptionTransaction extends OptionTransaction {
  def x: String = "X"
}
class SellOptionTransaction extends OptionTransaction {
  def y: String = "Y"

}

trait Formatter[T] {
  def format(ot:T):String
}

object Formatter {
  def apply[T](implicit screen: Formatter[T]) = screen

  def selectFormatter[T](obj: T)(implicit formatter: Formatter[T]) = formatter

  implicit val buyOT = new Formatter[BuyOptionTransaction] {
    def format(ot: BuyOptionTransaction):String = ot.x.toString
  }

  implicit val sellOT = new Formatter[SellOptionTransaction] {
    def format(ot: SellOptionTransaction):String = ot.y.toString
  }

  implicit val ot = new Formatter[OptionTransaction] {
    def format(ot: OptionTransaction):String = ot match {
      case ot: BuyOptionTransaction =>
        selectFormatter(ot).format(ot)
      case ot: SellOptionTransaction =>
        selectFormatter(ot).format(ot)
    }
  }
}

def startFormat[T](ot: T)(implicit ev: Formatter[T]) = {
  ev.format(ot)
}
import Formatter._

val closeTransactions: List[OptionTransaction] = List(new BuyOptionTransaction, new SellOptionTransaction)

closeTransactions.map(startFormat(_))

答案 1 :(得分:1)

您可以collect选择合适的类型:

val closeTransactions: List[OptionTransaction] = ???
val buys = closeTransactions.collect { case b: BuyOptionTransaction => b}
val sells = closeTransactions.collect { case s: SellOptionTransaction => s}

现在您可以应用适当的类型类。

将所需的操作/转换添加到OptionTransaction特征并将其用于动态绑定可能更好。如果您只想继续为其中一个工作,请查看this answer