使用来自不同范围的导入时的 Scala 类型不匹配问题

Scala Type Mismatch issue when using import from different scope

在我的项目中(用 slick 3.0 玩 2.4),我有一个设置:使用 MySQL 进行生产,使用 H2 进行单元测试(开始觉得这是一个可怕的想法)。为此,我必须导入 slick.driver.JdbcProfile 而不是任何特定的驱动程序(例如 slick.driver.MySQLDriver)并将其 api._ 导入我的 DAO class,如下所示:

class SomeDAO(val context: MyContext){
  import context.profile.api._
  import context.SOME_TYPE

  def invoke(para: SOME_TYPE) = { ... }

  // other DBIO...

}

到目前为止一切正常,但是,我有一个服务 class 需要这个 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

}

当我尝试从完全相同的 context 实例中导入一个类型时出现问题,直观地说,我在这里使用的是“Same”类型,对吧?

有人可以解释这种行为并给出有关模式的提示以削减我写的这种 'non-sense' 吗?

通过将类型定义移动到 object 来减少痛苦,因此类型是静态导入的。

仍然不确定如何继承类型以及如何在其中引入一些动态组件object

更新: 它实际上在 Scala 中被称为 "Path Dependent Types"。

您正在使用依赖于路径的类型。它们实际上取决于路径,而不是其内容。

考虑这个例子:

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)
}

您可能会天真地认为 xy 实际上是相同的,它们共享相同的内容和相同的类型。真实的内容。错误的类型。编译器很好地为您提供了类型错误:

error: type mismatch;

found : dependent.Assign.x.Box[Int]

required: dependent.Assign.y.Box[Int]

但是你可以告诉编译器 xy 应该共享相同的路径相关类型,尽管它们是不同的文字路径

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)
  ...
}