Scala input: "Expected _ $ 1, got T"
I have a Lift project with mixed Java-Scala code. The project has a JPA backend written in Java with EclipseLink accessed by the Scala side that uses Lift and Lift-NG.
On the Java side, I have the following relevant interfaces:
interface IEntity
interface IDAO<T extends IEntity> {
void persist(T t);
}
On the Scala side, I have the following:
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)
}
}
The purpose of this hierarchy is to allow me to create Service instances that handle a given Binding for object E, which can also receive and use the corresponding DAO created to handle type E. For example:
// 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)
My problem is a compilation error that occurs inside the persist method of BasicService. On the last line, I get this:
Type mismatch: expected _$1, actual: IEntity
Since I'm a little inexperienced with Scala, I might be missing something very obvious with the type system, but I really can't figure it out. How can I get around this error?
source to share
Your definition BasicService
does not require the type argument to be B
:
B <: Binding[_ <: IEntity]
compatible with type argument dataAccessObject
:
dataAccessObject: IDAO[_ <: IEntity]
What if one Binding[FooEntity]
and the other IDAO[BarEntity]
?
You have to take the variable of the type E
you say you are trying to use and actually define it:
class BasicService[E <: IEntity, B <: Binding[E]]
(serviceName: String, dataAccessObject: IDAO[E])
Also note that in the above code example, a variable of type B
to BasicService
may not be needed because you only use it to get the binding
before argument persist()
. You could just use the type Binding[E]
there:
class BasicService[E <: IEntity]
(serviceName: String, dataAccessObject: IDAO[E]) {
def persist(binding: Binding[E]): Unit = // ...
}
source to share