3

我迷失在 scala 泛型中。

我需要一个storeUnit接受Unit' 子类的实例 (eq Visit) 并返回StoredUnit' 子类的实例 (eq StoredVisit) 的方法,但我收到编译错误。

trait StatsUnit { val ip: String } 
case class Visit(ip: String) extends StatsUnit
case class Click(ip: String) extends StatsUnit

trait StoredStatsUnit extends StatsUnit { val id: String }
case class StoredVisit(id: String, ip: String) extends StoredStatsUnit
case class StoredClick(id: String, ip: String) extends StoredStatsUnit

def storeUnit[A <: StatsUnit, B <: StoredStatsUnit](statsUnit: A): B = {
  statsUnit match {
    case x: Visit => StoredVisit("myid", x.ip)
    case x: Click => StoredClick("myid", x.ip)
  }
}

/tmp/1.scala:11: error: type mismatch;
 found   : this.StoredVisit
 required: B
    case x: Visit => StoredVisit("myid", x.ip)
                                    ^
/tmp/1.scala:12: error: type mismatch;
 found   : this.StoredClick
 required: B
    case x: Click => StoredClick("myid", x.ip)
4

3 回答 3

3

先来个评论:

  1. 不要说出你的特质UnitUnit在 Scala 中具有特定的含义——它相当于 Java 的void——并且遮蔽该定义只会造成麻烦!

但是,这里的问题是您指定您的方法将返回一个实例,B然后您尝试返回一些类型StoredVisit。在此示例中您根本不需要B,因此以下将正常工作:

def storeUnit[A <: StatsUnit](unit: A): StoredStatsUnit = {
  StoredVisit("myid", unit.ip)
}
于 2013-02-07T16:12:56.680 回答
3

让我们对编译器撒谎以使代码编译,然后我将展示编译器在抱怨什么。第一的:

scala> def storeUnit[A <: StatsUnit, B <: StoredStatsUnit](unit: A): B = {
     |   StoredVisit("myid", unit.ip).asInstanceOf[B]
     | }
storeUnit: [A <: StatsUnit, B <: StoredStatsUnit](unit: A)B

现在让我们创建另一个子类StoredStatsUnit

case class UnStoredVisit(id: String, ip: String, n: Int) extends StoredStatsUnit

现在让我们看看为什么编译器会抱怨那个方法定义:

scala> val visit: UnStoredVisit = storeUnit(Visit("1.2.3.4"))
java.lang.ClassCastException: StoredVisit cannot be cast to UnStoredVisit

换句话说,您不会返回一个参数化的 B ,它是StoredStatsUnit. 您正在返回 a StoredVisit,它是它的一个特定子类。

于 2013-02-07T17:29:54.360 回答
1

B是 的子类型StoredUnit并且StoredVisit是 的子类型,StoredUnit但没有StoredVisit与 兼容的有效推论B

于 2013-02-07T16:14:44.567 回答