栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

速晓covariance, contravariance (协变、逆变)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

速晓covariance, contravariance (协变、逆变)

 前言

        英词成群,非舞文弄墨。固知义足矣,译徒增负也。何以弃译知义,初篇答之。

正文

        刚才复习这个知识点,中网、外网上都说得很模糊。并且这个特性在很多种语言中都有,我便总结一下。为尽可能照顾广大读者,用 Java 和 Kotlin 写了示例。示例很简单,如果某些语言特性不知道的话自己猜想一下便可以了,你猜的基本都是对的。

初衷

        先从初衷讲起,我认为所有教学都该这样。

        先列出三个 class,A 为 B的 superclass,B 为 C 的 superclass。( superclass 指父类,subclass 指子类) 

class A{
    int a = 0;
}

class B extends A {
    int b = 1;
}

class C extends B {
    int c = 2;
}

对于这样一个方法

void siteTest(List list){...}

如果存在一个参数,其类型为 List 或者 List, 它是传递不到 siteTest 这个方法中的。因为在 siteTest 中使用该参数时存在安全隐患(见下文),IDE(开发工具) 便禁止了。但如果 IDE 针对这种情况在写代码时加一些限制以确保安全,不就提高很多效率了吗,此即设计 covariance, contravariance的初衷。

Covariance

先用 wildcard (通配符)  在 Java 中类似实现,如下图。

如上,将类型为 List 的 cs 传递给方法 outSiteTest,IDE 会自动对 list 限制为只读,这样便杜绝了安全隐患。

        如果在设计 List 时就一并实现的话,便是 covariance,如下

//interface 换成 class 也是可以的
interface List{}
//如果再限制 T 为 A 的 subclass,便是
interface List{}

这样在方法 outSiteTest 中将 List 写为 List 就可以了。当然这只是为了举例说明,Java 的 class 或 interface 并不支持这样设计。不过很多其他语言都是支持的,如果用 Kotlin 来写的话便是这样:

interface List
//或者
interface List

一般其他语言也都会在 covariance 中采用 out,这样设计是为了帮你更好理解所限制的使用范围。这时 IDE 会限制在 List 的子类中,全局 T 型变量只能为 private,对于非 private 的方法,T 只能出现在其括号外部(out)。试想一下,这样是不是就限制 T 型变量为只读了。

        上述只是为了举例,Kotlin 中的 List 并没有这样设计。

        此外,如果安全隐患可被自己手动排除呢。比如在写库的时候,自己明确知道会传进来哪些参数,可以使用哪些参数。在图中的例子里,cs 经 outSiteTest 使用后,如果在其他地方不对 cs 那个位置上的 element(元素) 取 c,是不是就安全了。Kotlin 为此提供了解决方法,对确保安全的参数不再限制,只要在其类型 T 前加一个注解 UnsafeVariance 就可以了,如下

class OutSite (var value: @UnsafeVariance T)

此时 value 为 private,但方法 getValue,setValue 均为 public。此外在方法中单独声明也是可以的,但这样就不能用 @UnsafeVariance 来解除限制了,如下:

fun outSiteTest(v:InSite){}

每种语言的解决方法不太一样,也可能并不支持解决,就不一一介绍了。
 

Contravariance

        先用 wildcard  在 Java 中类似实现,如下图。

此时 IDE 会在 inSiteTest 中对 list 限制为只写,排除安全隐患。在其他语言中实现 contravariance 类比之前的 covariance,把 out 改为 in 即可,以限制 T 只能出现在 public 的方法括号内部(in),内含的全局 T 型变量同样只能为 private。

至此,已经把 covariance 和 contravariance 介绍完毕,相信你已经领悟了。

不定期更新

另有三个微信公众号,前者针对整个计算机领域,后两者针对安卓领域。公众号可以根据需要分开关注,更新得也会快一些,欢迎浏览。

愿意打赏可以扫码,多谢。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/329061.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号