在我的项目(玩 2.4 和 slick 3.0)中,我有一个设置:使用 MySQL 进行生产,使用 H2 进行单元测试(开始觉得这是一个可怕的想法)。为此,我必须导入 slick.driver.JdbcProfile
而不是任何特定的驱动程序(例如 slick.driver.MySQLDriver
)并导入其 api._
在我的 DAO 类中,如下所示:
class SomeDAO(val context: MyContext){
import context.profile.api._
import context.SOME_TYPE
def invoke(para: SOME_TYPE) = { ... }
// other DBIO...
}
到目前为止,一切都很好,但是,我有一个需要此 DAO 的服务类,以及上下文中的类型作为参数:
class MyService(val context: MyContext){
val someDAO = new SomeDAO(context)
import someDAO.context.SOME_TYPE // it works
// import context.SOME_TYPE // Type mismatch! But how to avoid it???
def invokeDAOMethod(para: SOME_TYPE) = someDAO.invoke(para) // where mismatch occurred
// expect: MyService.this.someDao.context.SOME_TYPE
// actual: MyService.this.context.SOME_TYPE
}
当我尝试从完全相同的上下文
实例导入类型时,就会出现问题,直观地说,我在这里使用“相同”类型,对吗?
有人可以解释这种行为并给出一些模式提示来减少我写的这种“无意义”吗?
最佳答案
您正在使用路径相关类型。它们实际上依赖于路径,而不是其内容。
考虑这个例子:
class Store {
case class Box[T](box : T)
def box[T](b : T) = Box[T](b)
def unbox[T](b : Box[T]) : T = b.box
}
object Assign {
val x = new Store()
val y = x
val box = x.box[Int](2)
val ub = y.unbox[Int](box)
}
您可能天真地认为x
和y
实际上是相同的,它们共享相同的内容和相同的类型。内容真实。类型错误。编译器很好地为您提供了类型错误:
error: type mismatch;
found : dependent.Assign.x.Box[Int]
required: dependent.Assign.y.Box[Int]
但是您可以告诉编译器,x
和 y
应该共享相同的路径相关类型,尽管文字路径不同
object Assign {
val x = new Store()
val y : x.type = x
val box = x.box[Int](2)
val ub = y.unbox[Int](box)
}
使用 val y : x.type = x
编译器将会成功。
您的问题具有相似的性质,解决方案也相似:您应该明确指定类型等效性。更改 SameDAO 定义以接受类型参数
class SomeDAO[MC <: MyContext](val context: MC){
...
}
并在创建时传递适当的类型:
class MyService(val context: MyContext){
val someDAO = new SomeDAO[context.type](context)
...
}
关于使用从不同范围导入时的 Scala 类型不匹配问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32692936/