Scala打字:"预计_ $ 1,得到T"

时间:2014-08-13 11:02:53

标签: scala generics

我有一个带有混合Java-Scala代码的Lift项目。该项目有一个用Java编写的带有EclipseLink的JPA后端,由Scala端访问,后者使用Lift和Lift-NG。

在Java方面,我有以下相关接口:

interface IEntity

interface IDAO<T extends IEntity> {
    void persist(T t);
}

在Scala方面,我有以下内容:

abstract class Binding[T <: IEntity] extends NgModel {
    def unbind: T
}

class BasicService[B <: Binding[_ <: IEntity]](serviceName: String, dataAccessObject: IDAO[_ <: IEntity]) {
    def persist(binding : B): Unit = {
        val entity = binding.unbind
        dataAccessObject.persist(entity)
    }
}

此层次结构的目的是让我创建处理实体E的给定绑定的Service实例,它还可以接收和使用为处理类型E而创建的适当DAO。例如:

// Java side
class Todo implements IEntity

class TodoManager implements IDAO<Todo>

// Scala side
case class TodoBinding extends Binding[Todo] {
    override def unbind: Todo = new Todo()
}
object HelloWorld extends BasicService[TodoBinding]("todoService", new TodoManager) 

我的问题是在BasicService的persist方法中发生的编译错误。在最后一行,我明白了:

Type mismatch: expected _$1, actual: IEntity

由于我对Scala缺乏经验,我可能会遗漏一些类型系统非常明显的东西,但我真的无法弄清楚这一点。我该如何解决这个错误?

1 个答案:

答案 0 :(得分:3)

您对BasicService的定义不要求B的类型参数:

B <: Binding[_ <: IEntity]

dataAccessObject

的类型参数兼容
dataAccessObject: IDAO[_ <: IEntity]

如果一个是Binding[FooEntity]而另一个是IDAO[BarEntity]怎么办?

您应该使用您说要尝试使用的类型变量E,并实际定义它:

class BasicService[E <: IEntity, B <: Binding[E]]
                  (serviceName: String, dataAccessObject: IDAO[E])

另请注意,在您发布的示例代码中,可能不需要类型变量BBasicService,因为您只使用它来接收参数binding到{{1 }}。您可以在那里使用persist()类型:

Binding[E]