我正在尝试使用强类型行数据访问来建模类似于集合的集合。我正在使用F-bounded多态(递归类型)模式,以便通过转换携带表类型信息(例如,访问DataView中的列列表是表过滤的结果)。只要使用实际类型,一切正常。请查看下面的代码片段,了解有问题的常见超类型操作。
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]
最后一行产生编译错误:
for(counter | test | action){}
似乎自我类型边界不会保留在替代Table1和Table2的类型中。是否有任何已知的解决方法?
更新: 如果我错了,请纠正我,但我认为我错误地认为Table1和Table2有共同的超类型,它具有DataTable的特征。它们具有DataTable [_]的常见超类型,但这不再是有效的DataTable - 这正是scala编译器试图告诉我的内容:)。
确实可以尝试使用存在类型,但是引入GenericDataTable类型作为DataTable [A]的基础可以更直接的方式解决问题。
在我的情况下 - 遗憾的是,这并不容易 - 因为它需要构建互连类的另一个赞美层次结构。
的Marcin
答案 0 :(得分:0)
我自己也想了解了一些问题:
getTable的返回类型是:
def getTable(name: String): DataTable[_ >: Table1 with Table2 <: DataTable[_ >: Table1 with Table2]]
实际上是DataTable[_]
以下代码也失败了:
val tbl: DataTable[_] = new Table1
dump(tbl)
由于转储期望DataTable
的某个特定子类型,并且它得到其抽象类型DataTable[_]
,因此很有意义。
所以,如果具体的子类型隐藏在它的抽象超类型后面,我怀疑F-bounded是否有意义:如果输入类型是DataTable[_]
,如果你能推断出特定的子类型,我会感到惊讶它背后的对象是静态的。
由于getTables
可以返回更多类型的DataTable
,因此其返回类型可能不会比DataTable[_]
更具体。确实在这方面工作是最有希望的途径,但评论中建议的解决方案不是编译:
def getTable(name: String): A forSome { type A <: DataTable[A] }
编辑:我做到了!这很奇怪!:
type DataTableSubtype = A forSome {type A <: DataTable[A]}
def convertToSubtype(tbl:DataTableSubtype): DataTableSubtype = tbl
def getTable(name: String): DataTableSubtype = {
name match {
case "Table1" => {convertToSubtype(new Table1)}
case "Table2" => {(new Table2())}
}
}
dump(getTable("Table1"))
诀窍是强制至少一个返回的表格为A forSome {type A <: DataTable[A]
类型!因此,各种子类型对象的工厂可以公开返回对象的具体类型!我不得不说,心灵不好。
我必须指出转储可能只是:
def dump(table: DataTable[_]): Unit
当输入类型也是我们在第一时间使用F-bounded类型的返回类型时,例如:
def id[A <: DataTable[A]](table: A): A = table
因为这会使我们无法获取Table1并返回Table2。
总而言之,F-bounded方法(这是创建F-bound类型的动机)在输入类型是F-bounded的具体子类型时有意义类型,类型在返回类型中使用,直接用作A
或间接用作Something[A]
。
答案 1 :(得分:0)
这是catch-22的scala版本。
你已经省略了返回类型,scala默默地错误计算它并给出你无关的错误。
万恶之源: DataTable[_]
不是定义为DataTable[A <: DataTable[A]]
的F-bounded类型的正确存在类型它是DataTable[A] forSome {type A <: Any}
<的简写em> F-bound 在这里丢失了。正确的类型是DataTable[A] forSome { type A <: DataTable[A] }
Scala的不当行为:当有疑问时,类型检查器会将类型推断为类似DataTable[_]
的类型。好吧,它的精确度稍高,但仍然在失去 F-bound 。
所以答案是定义正确的类型并明确指定它:
object DataTable {
type Any = DataTable[A] forSome {type A <: DataTable[A]}
}
def getTable(name: String) : DataTable.Any = // fill here