Scala中如何实现Java风格的协变、逆变泛型约束列表
Scala中对应Java泛型通配符的等效写法
嘿,刚好我之前也纠结过这个问题,现在给你梳理清楚Scala里怎么写出和Java那两行代码等效的实现!
首先得明确Scala和Java泛型的一个核心区别:Scala的很多集合(比如不可变List)本身就声明了协变(List[+A]),这意味着如果Siamois是Chat的子类,那么List[Siamois]自动就是List[Chat]的子类型——这和Java不一样,Java里List[Siamois]不能直接赋值给List[Chat],必须用? extends来放宽类型约束。
不过如果你想要完全对应Java里的通配符写法(不管集合本身的协变性),或者处理可变集合的场景,写法如下:
对应Java的List<? extends Chat> chats = new ArrayList<Siamois>();
在Scala里,你可以用上界通配符_ <: Chat来实现,代码如下:
// 不可变List的写法 val chats: List[_ <: Chat] = List[Siamois]() // 如果是可变集合(比如ListBuffer),写法类似 import scala.collection.mutable.ListBuffer val mutableChats: ListBuffer[_ <: Chat] = ListBuffer[Siamois]()
当然,因为Scala的不可变List是协变的,你其实也可以直接写val chats: List[Chat] = List[Siamois](),这和上面的通配符写法效果一致,而且更简洁——这是Scala协变带来的便利。
对应Java的List<? super Siamois> siamois2 = new ArrayList<Chat>();
这里需要用下界通配符_ >: Siamois,对应Java的? super,代码示例:
// 不可变List的写法 val siamois2: List[_ >: Siamois] = List[Chat]() // 可变集合的写法 val mutableSiamois2: ListBuffer[_ >: Siamois] = ListBuffer[Chat]()
这种写法的场景通常是你需要往集合里添加Siamois或其子类型的元素,就像Java里? super允许你写入子类型元素一样。
最后再总结一下:
- Scala的
_ <: A≈ Java的? extends A(上界通配符,更适合读取操作) - Scala的
_ >: A≈ Java的? super A(下界通配符,更适合写入操作)
内容的提问来源于stack exchange,提问作者David Tavan
相关产品推荐
相关产品推荐

