scala - Structural types with generics in Scala
问题描述
I tried to define a structural type which is matched to an instance with a generic type. Like in this example code:
class ExampleTest extends FlatSpec with Matchers {
def add[T](container: {def add(s: T): Boolean})(element: T): Unit = {
container.add(element)
}
val set = new java.util.HashSet[String]()
add(set)("3")
set.contains("3") shouldEqual true
val list = new java.util.LinkedList[String]()
add(list)("3")
list.contains("3") shouldEqual true
}
but I get a compilation error:
Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
def add[T](container: {def add(s: T): Boolean})(element: T): Unit = {
When I get rid of the generic type in the method and write the code like this:
class ExampleTest extends FlatSpec with Matchers {
def add(container: {def add(s: String): Boolean}): Unit = {
container.add("3")
}
val set = new java.util.HashSet[String]()
add(set)
set.contains("3") shouldEqual true
val list = new java.util.LinkedList[String]()
add(list)
list.contains("3") shouldEqual true
}
it compiles but I get a runtime exception:
java.lang.NoSuchMethodException: java.util.HashSet.add(java.lang.String)
My question is: How to correctly define the structural type, so it can work with Java collections?
Note that it cannot replace them with Scala collection (it will be used with a Java library).
解决方案
尝试
import scala.language.reflectiveCalls
def add[T](container: {def add(s: Any): Boolean})(element: T): Unit = {
container.add(element)
}
val set = new java.util.HashSet[String]()
add(set.asInstanceOf[{def add(s: Any): Boolean}])("3")
set.contains("3") shouldEqual true
val list = new java.util.LinkedList[String]()
add(list.asInstanceOf[{def add(s: Any): Boolean}])("3")
list.contains("3") shouldEqual true
java.util.HashSet#add
(实际上java.util.AbstractCollection#add
)的签名并且java.util.LinkedList#add
是
boolean add(E e)
结构类型的反射调用在运行时解决。在运行时,由于类型擦除,泛型E
只是Any
(又名Object
)。
更多细节:具有泛型类型的结构类型
推荐阅读
- sql - 找出列是否包含每个组的两个不同值
- ajax - ajax成功方法上动态创建的DOM元素
- laravel - 运行命令 schedule laravel 时如何解决“致命错误:内存不足...”?
- sql - Postgres 查询计划器调优
- python-3.x - 使用 pyinstaller 从 .py 创建的 exe 存在 tensorflow 路径问题
- c# - asp.net core 2.0 控制台应用程序文件notfoundexception system.runtime 4.2.0.0
- python - 分而治之找到一个列表的最大和子列表
- python - 如何从表格中计算 pyspark 中的每周平均值?
- react-native - 在发布版本中反应原生地图崩溃
- c# - 无法转换 ICollection
到 IEnumerable