Scala中类型类的向下转换

Scala中类型类的向下转换,scala,casting,typeclass,implicit,downcast,Scala,Casting,Typeclass,Implicit,Downcast,我有 trait OptionTransaction { def data: Data } BuyOptionTransaction extends OptionTransaction SellOptionTransaction extends OptionTransaction 我将它们与格式化程序类型类一起使用,以创建各种事务的字符串表示形式 trait Formatter[T] { def format(ot:T):String } object Formatter {

我有

trait OptionTransaction {
  def data: Data
}

BuyOptionTransaction extends OptionTransaction
SellOptionTransaction extends OptionTransaction
我将它们与格式化程序类型类一起使用,以创建各种事务的字符串表示形式

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
向下转换到
BuyOptionTransaction
SellOptionTransaction
,否则它将找不到隐式格式设置程序


如何自动实现此向下播放?

您可以
收集相应的类型:

val closeTransactions: List[OptionTransaction] = ???
val buys = closeTransactions.collect { case b: BuyOptionTransaction => b}
val sells = closeTransactions.collect { case s: SellOptionTransaction => s}
现在可以应用适当的类型类了


最好将您想要的操作/转换添加到
OptionTransaction
特性中,并将其用于动态绑定。如果您只想为其中一个继续工作,请看一看。

如果您想处理多态运行时,您需要实现某种动态(运行时)调度,而不是静态(编译时)类型类。它可能是这样的:

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(_))

是的,我知道收集,但它涉及我做
manual
cast。一定还有别的办法。此外,我在示例代码中显示了两种以上的事务类型。我将检查另一个答案。在这种情况下,我建议将基本特征(
OptionTransaction
密封,并检查以生成泛型实现。我想我可能会选择协同产品方式。您可以更改
OptionTransaction
及其派生类的定义吗?通常人们只需将抽象的
格式
添加到
OptionTransaction
中,并根据需要在派生类中实现它,就可以得到非常简单有效的解决方案。。。我想我已经回答了一个足够类似的问题,因此可以将其标记为副本: