什么是协变 逆变啊什么是协变 逆变,什么是协强,二者之间的关系

什么是协变返回类型?-java,oop,协方差covariance-CodeGo.net
什么是协变返回类型?
什么是Java中的协变返回类型?在一般的面向对象的编程?
我知道,这是一个“它只是谷歌”,我做到了,并且找到了答案,但我问反正二氧化硫的目标是排名优先的谷歌结果的编程问题。
本文地址 :CodeGo.net/106616/
-------------------------------------------------------------------------------------------------------------------------
1. 协变回传,也就是说,当一个重写的返回类型的允许是返回类型的子类型。
为了澄清这有一个例子,是个案Object.clone()-这是声明为返回一个类型的Object。你可以在自己的类中重写这个如下:
public class MyFoo
// Note covariant return here, method does not just return Object
public MyFoo clone()
// Implementation
这里的好处是,它保存一个明确的参照MyFoo对象将能够调用clone()并且知道(不压铸)的返回值是一个实例MyFoo。如果没有协变返回类型,在MyFoo就必须声明为返回Object-所以调用代码必须显式地调用向下转换的结果(甚至认为双方“知道”它永远只能是MyFoo的一个实例)。
请注意,没有什么特别之处clone()而任何可以有一个协变返回-它在这里作为一个例子 CodeGo.net,因为它是一个地方,这是
本文标题 :什么是协变返回类型?
本文地址 :CodeGo.net/106616/
Copyright (C) 2017 CodeGo.net[转]C#4.0中的协变和逆变
时间: 13:07:04
&&&& 阅读:79
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&
谈谈.Net中的协变和逆变
关于协变和逆变要从面向对象继承说起。继承关系是指子类和父类之间的关系;子类从父类继承所以子类的实例也就是父类的实例。比如说Animal是父类,Dog是从Animal继承的子类;如果一个对象的类型是Dog,那么他必然是Animal。
协变逆变正是利用继承关系 对不同参数类型或返回值类型 的委托或者泛型接口之间做转变。我承认这句话很绕,如果你也觉得绕不妨往下看看。
如果一个方法要接受Dog参数,那么另一个接受Animal参数的方法肯定也可以接受这个方法的参数,这是Animal向Dog方向的转变是逆变。如果一个方法要求的返回值是Animal,那么返回Dog的方法肯定是可以满足其返回值要求的,这是Dog向Animal方向的转变是协变。
由子类向父类方向转变是协变 协变用于返回值类型用out关键字
由父类向子类方向转变是逆变 逆变用于方法的参数类型用in关键字
协变逆变中的协逆是相对于继承关系的继承链方向而言的。
一. 数组的协变:
Animal[] animalArray = new Dog[]{};
上面一行代码是合法的,声明的数组数据类型是Animal,而实际上赋值时给的是Dog数组;每一个Dog对象都可以安全的转变为Animal。Dog向Animal方法转变是沿着继承链向上转变的所以是协变。
二. 委托中的协变和逆变
1.委托中的协变
//委托定义的返回值是Animal类型是父类public delegate Animal GetAnimal();//委托方法实现中的返回值是Dog,是子类static Dog GetDog(){return new Dog();}//GetDog的返回值是Dog, Dog是Animal的子类;返回一个Dog肯定就相当于返回了一个Animal;所以下面对委托的赋值是有效的GetAnimal getMethod = GetD
2.委托中的逆变
//委托中的定义参数类型是Dogpublic delegate void FeedDog(Dog target);//实际方法中的参数类型是Animalstatic void FeedAnimal(Animal target){}// FeedAnimal是FeedDog委托的有效方法,因为委托接受的参数类型是Dog;而FeedAnimal接受的参数是animal,Dog是可以隐式转变成Animal的,所以委托可以安全的的做类型转换,正确的执行委托方法;FeedDog feedDogMethod = FeedA
定义委托时的参数是子类,实际上委托方法的参数是更宽泛的父类Animal,是父类向子类方向转变,是逆变。
三. 泛型委托的协变和逆变:
1. 泛型委托中的逆变
如下委托声明:
public delegate void Feed&in T&(T target);
Feed委托接受一个泛型类型T,注意在泛型的尖括号中有一个in关键字,这个关键字的作用是告诉编译器在对委托赋值时类型T可能要做逆变。
//先声明一个T为Animal的委托Feed&Animal& feedAnimalMethod = a=&Console.WriteLine(“Feed animal lambda”);//将T为Animal的委托赋值给T为Dog的委托变量,这是合法的,因为在定义泛型委托时有in关键字,如果把in关键字去掉,编译器会认为不合法Feed&Dog& feedDogMethod = feedAnimalM
2. 泛型委托中的协变
如下委托声明:
public delegate T Find&out T&();
Find委托要返回一个泛型类型T的实例,在泛型的尖括号中有一个out关键字,该关键字表明T类型是可能要做协变的。
//声明Find&委托Find& findDog = ()=&new Dog();//声明Find&委托,并将findDog赋值给findAnimal是合法的,类型T从Dog向Animal转变是协变Find& findAnimal = findD
四. 泛型接口中的协变和逆变:
泛型接口中的协变逆变和泛型委托中的非常类似,只是将泛型定义的尖括号部分换到了接口的定义上。
1.泛型接口中的逆变
如下接口定义:
public interface IFeedable&in T&{void Feed(T t);}
接口的泛型T之前有一个in关键字,来表明这个泛型接口可能要做逆变
如下泛型类型FeedImp,实现上面的泛型接口;需要注意的是协变和逆变关键字in,out是不能在泛型类中使用的,编译器不允许
public class FeedImp&T&:IFeedable&T&{
public void Feed(T t){
Console.WriteLine(“Feed Animal”);
来看一个使用接口逆变的例子:
IFeedable& feedDog = new FeedImp&();
上面的代码将FeedImp类型赋值给了IFeedable的变量;Animal向Dog转变了,所以是逆变.
2.泛型接口中的协变
如下接口的定义:
public interface IFinder&out T& {
T Find();}
泛型接口的泛型T之前用了out关键字来说明此接口是可能要做协变的;如下泛型接口实现类。
public class Finder&T&:IFinder&T& where T:new(){
public T Find(){
return new T();
使用协变,IFinder的泛型类型是Animal,但是由于有out关键字,我可以将Finder赋值给它.
IFinder& finder = new Finder&();
协变和逆变的概念不太容易理解,可以通过实际代码思考理解。这么绕的东西到底有用吗?答案是肯定的,通过协变和逆变可以更好的复用代码。复用是软件开发的一个永恒的追求。
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:&&&&&&&&&&&&原文:http://blog.csdn.net/honantic/article/details/
教程昨日排行
&&国之画&&&& &&&&&&
&& &&&&&&&&&&&&&&
鲁ICP备号-4
打开技术之扣,分享程序人生!在刚刚落下帷幕的PDC上,我们得到了很多振奋的消息,包括C# 4.0及VS2010等等。Anders Liu 已经
出来,那里面有非常详细的介绍。
C#的发展是很快很快的,C#的设计目的是成为一个有趣有用通用的程序语言,并因此让使用该语言的用户能获得更大的成功。所以,C#除了面向对象的基本特征外,现在引入了相当多的其他特征喔!
动态,动态。动态是目前超级流行的词汇。C#也要动起来了喔!
C# 4.0的主要主题是动态编程。对象的意义变得越来越&动态&,它们的结构和行为无法通过静态类型来捕获,或者至少编译器在编译程序时无法得知对象的结构和行为。
相关的特性有动态查找、命名参数、可选参数等。
还有,简化了与COM的互操作。
还有,协变和逆变 Covariance and contravariance 。
这些都在白皮书里可以找到介绍。我在这里整理一下协变和逆变的一些参考资料,本来数学就不好,怕过一两天就又忘了,俗话说,好记性不如烂笔头嘛。
首先看看问题的引入。
这里有两个类型,T 和 U,在这两个类型间,以下伪表达式肯定有一个是&真&:
T 和 U 没有任何关系
例如有这些类型:动物 Animal、哺乳动物 Mammal、爬行动物 Reptile、长颈鹿 Giraffe、老虎 Tiger、蛇 Snake和海龟 Turtle,它们之间的继承关系(应该来个UML就一目了然了)有:哺乳动物是动物的一个子类,长颈鹿是哺乳动物的一个子类等等&&
那么就有:哺乳动物比长颈鹿大,比动物小,等于哺乳动物,和爬行动物却没有关系(这里的比较都不是对象之间的比较,要注意哦。)
呃,如果这个难于理解,我们再看看程序中的情况。假设有一个变量,这个变量在C#中有一个容身之处(不是说的存储区的物理地址),每一个变量在C#中的容身之处都对应一个类型(强类型语言就是这样的),那么,在运行时你可以在一个特定的容身之处存储对应类型的实例或者小于这个类型的类型的实例(拗口-,-)。所以呢,哺乳动物对象对应的容身之处可以存储一个长颈鹿,但是不能存储一个海龟。(考虑面先接口编程和抽象基类的思想)
容身之处这个例子说明的是&交换原则&,跟面向接口编程和抽象基类的机制很类似,也就是在很多地方,我们用子类代替基类(或接口或抽象类)来使用。
现在来定义什么是协变:一个操作如果在 T 和 U 两个类型上执行后返回的 T' 和 U' 之间的关系跟原来的 T 和 U 之间的关系(上面那4个伪表达式)相同,则这个操作就叫做协变。英文名:Covariance。
再看看什么是逆变:一个操作如果将 T 和 U 的大小关系改变了(大变小,小变大 - 逆转),但是不改变 T 和 U 之间的相等或不相干这两个关系,则这个操作就叫做逆变。英文名:Contravariance。
呃呃。变来变去,头已经晕了。
(还没完,等我喔!)
阅读(...) 评论()扫二维码下载作业帮
1.75亿学生的选择
下载作业帮安装包
扫二维码下载作业帮
1.75亿学生的选择
物理中什么是协变?什么是协强?两者什么关系?
扫二维码下载作业帮
1.75亿学生的选择
两者关系还请楼主自己深刻理解 本人学识短浅
为您推荐:
其他类似问题
扫描下载二维码}

我要回帖

更多关于 协变张量和逆变张量 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信