【发布时间】:2016-02-01 08:07:10
【问题描述】:
我正在尝试使用强类型行数据访问来建模类似表格的集合。我正在使用 F 有界多态性(递归类型)模式,以便通过转换携带表类型信息(例如,访问 DataView 中的列列表是表过滤的结果)。一切正常,只要使用实际类型。请查看下面的 sn-p 以了解有问题的常见超类型操作。
trait DataTable[A <: DataTable[A]] { self: A =>
def table: A = self
def name: String
}
class Table1 extends DataTable[Table1] {
val name = "Table1"
}
class Table2 extends DataTable[Table2] {
val name = "Table2"
}
def dump[A <: DataTable[A]](table: A) = println(table.name)
def getTable(name: String) = name match {
case "Table1" => new Table1
case "Table2" => new Table2
}
dump(new Table1())
dump(getTable("Table1") // doesn't typecheck...
最后一行产生编译错误:
inferred type arguments [DataTable[_2]] do not conform to method dump's type parameter bounds [A <: DataTable[A]]
found: DataTable[_2] where type _2 >: Table1 with Table2 <: DataTable[_ >: Table1 with Table2 <: Object]
似乎在 Table1 和 Table2 的替代类型中没有保留 self 类型边界。是否有任何已知的解决方法?
更新: 如果我错了,请纠正我,但我认为我错误地假设 Table1 和 Table2 具有共同的超类型,它具有 DataTable 的特性。它们有共同的 DataTable[_] 超类型,但这不再是有效的 DataTable - 这正是 scala 编译器试图告诉我的:)。
确实可以尝试使用存在类型,但引入 GenericDataTable 类型作为 DataTable[A] 的基础会以更直接的方式解决问题。
就我而言——不幸的是,这并不容易——因为它需要构建另一个相互关联的类的互补层次结构。
马辛
【问题讨论】:
-
查看@tpolecat 关于这个主题的文章 - tpolecat.github.io/2015/04/29/f-bounds.html
-
这取决于你想对
getTable的结果做什么,但是明确的A forSome { type A <: DataTable[A] }返回类型应该可以工作。