问题
I have a Scala class that is trying to implement a Java interface (EntityManager in JavaEE 7 for unit testing purposes to be specific). The interface has these two methods (among others):
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses);
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings);
In the Scala implementation I have:
override def createStoredProcedureQuery(procedureName: String, resultClasses: Class[_]*): StoredProcedureQuery = ???
override def createStoredProcedureQuery(procedureName: String, resultSetMappings: String*): StoredProcedureQuery = ???
However, I get the following error:
MyTest.scala:134: error: double definition:
method createStoredProcedureQuery:(procedureName: String, resultSetMappings: String*)javax.persistence.StoredProcedureQuery and
method createStoredProcedureQuery:(procedureName: String, resultClasses: Class[_]*)javax.persistence.StoredProcedureQuery at line 133
have same type after erasure: (procedureName: String, resultSetMappings: Seq)javax.persistence.StoredProcedureQuery
override def createStoredProcedureQuery(procedureName: String, resultSetMappings: String*): StoredProcedureQuery = ???
I have not been able to come up with a work around. My Google searches also failed to find and answer. I'm using Scala 2.10.4.
回答1:
AFAIK the EntityManager
Java interface cannot be implemented directly in Scala. The Java varargs are converted to Seq[Class[_]]
in the first method and Seq[String]
in the second method. Because of erasure, both methods then appear as having the same signature createStoredProcedureQuery(String, Seq[_])
.
I can only propose a workaround for this issue. You should write a Java abstract class that extends the EntityManager
interface and implement the 2 offending methods by delegating to 2 other abstract methods with different names in order to disambiguate:
public abstract class EntityManagerWorkaround implements EntityManager {
@Override
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) {
return createStoredProcedureQueryForResultClasses(procedureName, resultClasses);
}
@Override
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) {
return createStoredProcedureQueryForResultSetMappings(procedureName, resultSetMappings);
}
public abstract StoredProcedureQuery createStoredProcedureQueryForResultClasses(String procedureName, Class... resultClasses);
public abstract StoredProcedureQuery createStoredProcedureQueryForResultSetMappings(String procedureName, String... resultSetMappings);
}
Now you can extend the abstract class from Scala and implement the disambiguated methods:
class EntityManagerImpl extends EntityManagerWorkaround {
override def createStoredProcedureQueryForResultClasses(procedureName: String, resultClasses: Class[_]*) = ???
override def createStoredProcedureQueryForResultSetMappings(procedureName: String, resultSetMappings: String*) = ???
}
来源:https://stackoverflow.com/questions/24132089/how-to-implement-java-interface-in-scala-with-multiple-variable-parameter-method