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?

+3


source to share


1 answer


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 = // ...
}

      

+3


source







All Articles