我想要这个类型类:
abstract class Model[U](val query: TableQuery[ModelTable[U]]) {
// ...
}
但是在查询类型中有协方差。
我的想法是我有一个带U实例的函数,需要访问相应TableQuery [ModelTable [U]]的实例。 添加一个类型参数很讨厌,因为我不能再使用上下文边界来编写函数了:
def f[U : Mode](u: U) = // ...
每次都写出隐含的参数是非常麻烦的。 至于现在,我不明白为什么这是不可能的。给定U的具体类型,查询的类型约束对于编译器来说应该是微不足道的。
也许更具体:为什么不能编译:
// error: Unbound Wildcard Type
abstract class Model[U](val query: _ <: TableQuery[ModelTable[U]]) {
// ...
}
答案 0 :(得分:0)
query
参数已经是协变的。看来你有这样的问题:
class TableQuery[T]
class TableQuerySub[T] extends TableQuery[T]
class ModelTable[T]
class ModelTableSub[T] extends ModelTable[T]
class Model[U](val query: TableQuery[ModelTable[U]])
val x1: TableQuerySub[ModelTable[Int]] = ???
val x2: TableQuery[ModelTableSub[Int]] = ???
new Model(x1)
new Model(x2) // does not compile
此处x2
无法使用以下消息进行编译:
type mismatch;
found : TableQuery[ModelTableSub[Int]]
required: TableQuery[ModelTable[?]]
Note: ModelTableSub[Int] <: ModelTable[?],
but class TableQuery is invariant in type T.
You may wish to define T as +T instead. (SLS 4.5)
此处编译器告诉我们,它不确定TableQuery[ModelTableSub[_]]
是否扩展TableQuery[ModelTable[_]]
。为了告诉编译器这实际上是这种情况,我们需要创建TableQuery
协变的参数
class TableQuery[+T]
如果这对您没有帮助,请在您的问题中加入用例。
修改强>
添加第二个类型参数仍允许您指定上下文绑定。上下文绑定语法只不过是语法糖。以下陈述是相同的:
def f[U : Model](u:U) = {
val m = implicitly[Model[U]]
???
}
def f[U](u:U)(implicit m:Model[U]) = ???
有了这些知识,我们可以为具有多个参数的上下文添加上下文绑定:
class Model2[A, B]
def f[U](u:U)(implicit m:Model[_, U]) = ???
如果你真的想用上下文绑定语法来指定它,你可以这样做
type AnyModel2[B] = Model2[_, B]
def f[U : AnyModel2](u:U) = ???
没有类型别名,你会得到(在我看来不太可读)
def f[U : ({type T[x] = Model2[_, x]})#T](u:U) = ???