How to implement Java interface in Scala with multiple variable parameter methods (type eraser issue)?

ⅰ亾dé卋堺 提交于 2019-12-01 16:32:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!