在Scala中使用子类型和返回类型将通用对象处理为特定对象

pr1*_*001 1 scala subclass return-type covariance subtype

我认为这是关于协方差,但我对这个话题很弱......

我有一个通用的Event类用于数据库持久性之类的东西,让我们这样说:

class Event(
  subject: Long,
  verb: String,
  directobject: Option[Long],
  indirectobject: Option[Long],
  timestamp: Long)
{
  def getSubject = subject
  def getVerb = verb
  def getDirectObject = directobject
  def getIndirectObject = indirectobject
  def getTimestamp = timestamp
}
Run Code Online (Sandbox Code Playgroud)

但是,我有很多不同的事件动词,我想使用模式匹配等这些不同的事件类型,所以我将创建一些相应的case类:

trait EventCC
case class Login(user: Long, timestamp: Long) extends EventCC
case class Follow(
  follower: Long,
  followee: Long,
  timestamp: Long
) extends EventCC
Run Code Online (Sandbox Code Playgroud)

现在,问题是,如何轻松地将通用事件转换为特定的案例类.

这是我第一次尝试:

def event2CC[T <: EventCC](event: Event): T = event.getVerb match {
  case "login" => Login(event.getSubject, event.getTimestamp)
  case "follow" => Follow(
    event.getSubject,
    event.getDirectObject.getOrElse(0),
    event.getTimestamp
  )
  // ...
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这是错误的.

<console>:11: error: type mismatch;
 found   : Login
 required: T
             case "login" => Login(event.getSubject, event.getTimestamp)
                             ^
<console>:12: error: type mismatch;
 found   : Follow
 required: T
             case "follow" => Follow(event.getSubject, 
event.getDirectObject.getOrElse(0), event.getTimestamp)
Run Code Online (Sandbox Code Playgroud)

有没有比我更有类型的人解释是否,1)我想做什么是可能的(或者是合理的,对于那个问题),2)如果是,如何解决event2CC.谢谢!

Eri*_*ric 5

在我看来,你可以回归的最好的事情是EventCC:

def event2CC(event: Event): EventCC
Run Code Online (Sandbox Code Playgroud)

在编译时不能使T的类型更具体.只有在运行时才能知道T是否精确Login或者 Follow这只取决于事件值.