如何通过类型参数的类型别名

时间:2015-06-25 16:29:26

标签: scala generics type-erasure type-parameter type-alias

我想请求高级scala开发人员提供一些帮助。我的问题是我想访问属于类的类型参数的类型别名'父节点。

  case class MyModel(foo: String = "bar")

  case class MyDispatcher()

  trait Module[M, D] {
    type Dispatcher = D
    type Model = M
  }

  trait MySpecificModule[A <: Module[_, _]] {
    def dispatcher(): A#Dispatcher
  }

  class ModuleClass extends Module[MyModel, MyDispatcher] {
    //...
  }

  class MySpecificModuleClass extends MySpecificModule[ModuleClass] {
    override def dispatcher(): MyDispatcher = MyDispatcher()
  }

所以基本上MySpecificModule扩展了一般特征,并且应该知道dispatcher方法的类型。在MySpecificModuleClass的情况下,它应为MyDispatcher。但是当我尝试编译这段代码时,我得到了编译错误,因为方法的类型与定义的不一样:A#Dispatcher,但实际上它是。

Error:(21, 18) overriding method dispatcher in trait MySpecificModule of type ()_$2;
 method dispatcher has incompatible type
    override def dispatcher(): MyDispatcher = MyDispatcher()

             ^

我很感激您的建议。提前致谢, 的Gabor

解决

case class MyModel(foo: String = "bar")

case class MyDispatcher()

trait AbstractModule {
  type Dispatcher
  type Model
}

trait Module[M, D] extends AbstractModule {
  type Dispatcher = D
  type Model = M
}

trait MySpecificModule[A <: AbstractModule] {
  def dispatcher(): A#Dispatcher
}

class ModuleClass extends Module[MyModel, MyDispatcher] {
  //...
}

class MySpecificModuleClass extends MySpecificModule[ModuleClass] {
  override def dispatcher(): MyDispatcher = MyDispatcher()
}

1 个答案:

答案 0 :(得分:0)

我不完全理解Scala的推理,但是如果你摆脱类型参数,事情就会开始起作用:

case class MyModel(foo: String = "bar")

case class MyDispatcher()

trait Module {
  type Dispatcher
  type Model
}

trait MySpecificModule[A <: Module] {
  def dispatcher(): A#Dispatcher
}

class ModuleClass extends Module {
  type Model = MyModel
  type Dispatcher = MyDispatcher
  //...
}

class MySpecificModuleClass extends MySpecificModule[ModuleClass] {
  override def dispatcher(): MyDispatcher = MyDispatcher()
}

如果你真的希望拥有那些类型的参数,你可以引入一个辅助特征:

trait AbstractModule[M, D] extends Module {
  type Model = M
  type Dispatcher = D
}

class ModuleClass extends AbstractModule[MyModel,MyDispatcher]