- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
其实这是c#的老知识点了,但是今天发现同事对这个竟然还一知半解,就和他们讲解了下,顺便也回顾了下,同事我也把我对这个的全部理解,融化成几分钟的讲解,保证大家5分钟内全部理解,看不懂来打我.
目录
- 协变、逆变 解决的问题
- 泛型类型转换
- 原则核心
- 核心依据
- Out/In 输入输出?
- In示意图
- Out示意图
- 证明
- 问题点
比如Person类是Student的父类,我们平时可以直接:
Person A = new Student();
这是所谓的隐式转换,相信百分之999.99%的人都知道。 然后随着大家写代码越来越多,就会遇到这样的场景.
//我有一个集合
//我手上有一批学生
IEnumerable<Student> students = new List<Student>();
//我要他们先做人
IEnumerable<Person> peoples = students;
第一次看到这种代码,其实哪怕你一点不知道协变,逆变,你也觉得这是一段正常不过的代码,因为每个学生都是人,都可以直接转成 人 这个类型,那我一批学生不就是一批人吗。是的,你这样想绝对没错,不然微软怎么会能让你这样写没问题还编译通过呢? 但是如果我自己写一个:
//定义一个工作的泛型接口
public interface IWork<T>
{
}
实现类
public class Work<T> : IWork<T>
{
}
//直接报错
IWork<Person> work = new Work<Student>();;
现实给了我们当头一棒,这时候,我们应该找到 IEnumerable ,选中然后狠狠的F12去看一下,为什么官方的就可以。 我们发现官方在泛型前面多了一个out关键字。破案了~ 现在我们在我们的代码中也加入out关键字 。
public interface IWork<out T>
{
}
public class Work<T> : IWork<T>
{
}
IWork<Person> work = new Work<Student>();
OK~代码正常运行.
这里开始我们挑战五分钟速通,如果按照正常博客上来先讲概念,别说五分钟了,可能大家也就迷迷糊糊地看完了,所以我们直接整活.
正如数学的发展是从1+1=2作为开始,我们也需要一些真理来支撑我们讲下去。那么我们的核心依据就是: 里氏替换—— C#里,子类转父类可以直接隐式转换 就这么短,就完事了?对,记住就行!!! 。
讲到这里,我们继续忽悠,out是啥?来个翻译!不就是输出吗?in是啥,不就是输入吗?那么带入一下,Out不就是返回值吗,In不就是入参吗。那不就是方法的特征么。(先假设,再假设) 。
In:那么根据核心依据,子类转父类可以直接转,入参如果限定是Person类型,那么你给我限定为Student或者任意的Person类型的派生类,我都是可以接受的,因为都是安全的,可以直接转换过来的.
这种从基类转向派生类的兼容,就是所谓的逆变。 说白了,我让你给我一个人,你说不行,我给你找个学生,那肯定是满足需求的.
Out:Out代表的是返回值,根据核心依据,我返回的是Student类型,你说不行,你给我返回Person类型,那我不是笑开花了,我连Student都能返回,你让我返回父类,那我不是直接转就过去了,总归是类型安全的.
这种从派生类转向基类的兼容,就是所谓的协变。 说白了,我可以造个学生,结果你说给个人就行, 那不是so easy.
好了,我们说了这么多,至少证明下In/Out是代表的入参和返回值吧?直接show you code: 当Out作为返回值时的泛型没有问题,但是入参就报错了 当In作为入参时的泛型没有问题,但是返回值就报错了 。
好了,这还需要再解释吗?最后我们总结下,逆变和协变就是让 方法 有了泛型类型上的转换能力,强化了方法的多态能力.
1.属性为啥可以用逆变协变? 属性不就是get/set方法。 2.为什么接口和委托可以用逆变协变,类不行? 拜托你找一下共同点,接口和委托的共同点,都是行为,也就是方法为核心。接口里不能有字段。这也印证了我说的逆变协变最终是为方法服务的。 之所以类不行,我大概理解是方法和实例是分开的,本身不和实例存储在一起,也不是每个实例一份,如果逆变和协变可以服务类,那么会出现同样的类型,但是每个实例内部的同一个字段的类型都不一样,这对于存储和类型安全都是问题。 3.逆变和协变有啥用? 当你...设计问题,我就有遇到,有时候用上能更加优雅或者灵活的写代码吧,看你吧,少年.
最后此篇关于五分钟看完,彻底理解协变逆变的文章就讲到这里了,如果你想了解更多关于五分钟看完,彻底理解协变逆变的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
要在 R 中绘制正态分布曲线,我们可以使用: (x = seq(-4,4, length=100)) y = dnorm(x) plot(x, y) 如 dnorm将 y 计算为 x 的函数,R 是否
@XmlTransient 阻止将 JavaBeans 属性映射到 XML 表示。是否存在与此相反的情况,这意味着即使 WebService 未使用的方法也会被映射?如果这不可能,是否存在解决方法?
我有以下键数组: var keys = [{userId: "333"}, {userId: "334"}] 这个对象数组: var users = [ {id: "333", firstName:
我正在寻找将字符串转换为类型的通用方法。 例如: class SomeThing { public void Add(T value) { //... } pub
我看到了this question , 并弹出这个想法。 有没有一种在 PHP 中执行此操作的有效方法? 编辑 有演示最好吗? 最佳答案 你可以使用 pear 包 Math_Matrix为此。 关于矩
如何在 python 中求逆矩阵?我自己实现了它,但它是纯 python,我怀疑那里有更快的模块可以做到这一点。 最佳答案 你应该看看 numpy如果您进行矩阵操作。这是一个主要用C语言编写的模块,比
是否有比使用 IF ELSE 构造更简单的方法来反转 bool 值? 通常我会使用! bool 值前面。但这在 Navision 中不起作用 最佳答案 您可以使用 NOT 关键字代替 !。 关于nav
假设我有一个对象响应。现在我想检查一个 bool 变量,success,在 Response 下并做一个早期返回是 response 不成功。 if(response == null || !resp
任何人都可以提供/引用多维行主要顺序的“索引->偏移”*转换的倒数。此外,(伪)代码将不胜感激。 http://en.wikipedia.org/wiki/Row-major_order 举个例子,简
我有一个看起来像这样的系统: z1 = 5*x1 + x2*cos(x3) z2 = x1*sin(x3) + 3*x2 z3 = 3*x1 - 2*x2 这是微分方程组的变换(只是为了提供一些背景信
我正在使用org.apache.commons.math3.transform类FastFourierTransformer,我现在尝试在真实数据集上应用FFT,并应用逆FFT来获取原始数据集。我的问
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 年前。 Improve
背景 我需要使用已知的累积分布函数 (CDF) 从相当复杂的概率密度函数 (PDF) 中随机采样,并且我正在尝试使用 inverse transform sampling 。这应该很容易做到,因为我有
是否有任何 System.identityHashCode (object) 的逆函数能够从 System.identityHashCode (object) 的结果中提供对象的值? 最佳答案 Sys
有没有办法在mysql中获取group by语句的逆?我的用例是删除所有重复项。 假设我的表格如下所示: ID | columnA | ... 1 | A 2 | A 3 | A 4
我有一个查询,它给我一个公司列表(tblprov)及其相应的类别(tblrubro) 两个表通过查找表 (tblprovxrubro) 相关 SELECT p.id, p.name, r.idCat,
我有一个 jpg 图像,在矩形中有一个圆形物体,我想使圆形物体的环境透明... (本例去除红色区域) 借助这个iOS make part of an UIImage transparent和“UIBe
我想知道是否可以在不需要临时数组的情况下通过 Cholesky 分解获得矩阵的逆。截至目前,我可以在不使用临时数组的情况下进行 cholesky 分解,但从那里我还没有想出一种方法来获得原始矩阵的逆矩
是否可以在 Angular 中使用逆$watch? 我的问题 我使用 Angular-translate,并且我想对每个缺少的翻译使用 $http.put 。但我收到此错误: "10 $digets(
我正在执行 radix-2 dif 逆 fft。我正在使用共轭和缩放的属性来返回结果。我共轭我的输入 vector ,执行常规 radix-2 fft(不是 ifft),共轭结果,然后按 1.0/N
我是一名优秀的程序员,十分优秀!