scala 学习: 逆变和协变
scala 逆变和协变的概念网上有很多解释, 总结一句话就是
参数是逆变的或者不变的,返回值是协变的或者不变的。
但是为什么是这样的?
协变:

当s 是A的子类, 那么func(s) 是func(A)的子类。 也就是被参数化类型的泛化方向与参数类型的方向是一致的,所以称为协变。
个人理解的func(s) 是func(A)的子类的意思是: func(s)的返回值是func(A)的返回值的子类。
逆变:

同协变定义,但是是反过来,即当S是A的子类时,func(S)是func(A)的父类。
如下图所示:

为什么函数的参数是逆变 而函数的返回值是协变呢?

根据上面的解释: 入参是用来消费的, 如:animal > bird > dodo
假设有一个函数用来输出鸟类的叫声,func[-T], 这时 函数可以接受的参数为bird 和animal, 是合理的。
如果定义为func[+T], 函数接受的参数为 bird 和dodo, 对于参数为dodo类型来说,传另一个鸟如燕子, 则会出错。因此不符合要求。
scala> class Animal { val sound = "rustle" }
defined class Animal
scala> class Bird extends Animal { override val sound = "call" }
defined class Bird
scala> class Chicken extends Bird { override val sound = "cluck" }
defined class Chicken
假设你需要一个以Bird为参数的函数:
scala> val getTweet: (Bird => String) = // TODO
标准动物库有一个函数满足了你的需求,但它的参数是Animal。在大多数情况下,如果你说“我需要一个___,我有一个___的子类”是可以的。
但是,在函数参数这里是逆变的。如果你需要一个接受参数类型Bird的函数变量,但却将这个变量指向了接受参数类型为Chicken的函数,
那么给它传入一个Duck时就会出错。然而,如果将该变量指向一个接受参数类型为Animal的函数就不会有这种问题:
scala> val getTweet: (Bird => String) = ((a: Animal) => a.sound )
getTweet: Bird => String = <function1>
同理如返回值。
scala 学习: 逆变和协变的更多相关文章
- Scala 深入浅出实战经典 第81讲:Scala中List的构造是的类型约束逆变、协变、下界详解
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-97讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Java 逆变与协变
最近一直忙于学习模电.数电,搞得头晕脑胀,难得今天晚上挤出一些时间来分析一下Java中的逆变.协变.Java早于C#引入逆变.协变,两者在与C#稍有不同,Java中的逆变.协变引入早于C#,故在形式没 ...
- OOP中的逆变和协变
逆变和协变在存在于强类型语言中,尽管非常少提及.可是里面蕴含了面向对象的世界观.感谢和我一起讨论这个问题的人. 这里用了C#.Scala的语法作为演示样例.事实上逆变和协变的概念跟语言本身关系不大.事 ...
- Java中的逆变与协变
看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); ...
- C#4.0新特性(3):变性 Variance(逆变与协变)
一句话总结:协变让一个粗粒度接口(或委托)可以接收一个更加具体的接口(或委托)作为参数(或返回值):逆变让一个接口(或委托)的参数类型(或返回值)类型更加具体化,也就是参数类型更强,更明确. 通常,协 ...
- Java中的逆变与协变(转)
看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); ...
- Java 逆变与协变的名词说明
最近在研究Thinking in Java的时候,感觉逆变与协变有点绕,特意整理一下,方便后人.我参考于Java中的逆变与协变,但是该作者整理的稍微有点过于概念化,我在这里简单的说一下 我对于协变于逆 ...
- C# 逆变与协变
该文章中使用了较多的 委托delegate和Lambda表达式,如果你并不熟悉这些,请查看我的文章<委托与匿名委托>.<匿名委托与Lambda表达式>以便帮你建立完整的知识体系 ...
- .NET 4.0中的泛型逆变和协变
转载自:http://www.cnblogs.com/Ninputer/archive/2008/11/22/generic_covariant.html:自己加了一些理解 随Visual Studi ...
随机推荐
- 关于kindeditor中点击图片后,滚动条往上顶的bug
比如现在我插入两张图片, 无论我点击哪张图片,里边的滚动条都会往上顶. 本来以为往上会有解决方法,一查结果没有:然后想着去官网查查,然而什么都没有,想到官网提交这个bug,结果没地方提交. 怎么解决, ...
- elasticsearch的marvel
摘自: http://kibana.logstash.es/content/logstash/plugins/input/syslog.html 一:marvel介绍 marvel 是 Elastic ...
- cookie,session,sessionid
cookie,session,sessionid http协议是无状态的,意思是每次请求的状态不会保存.因此,产生了cookie,session之类保存会话状态的机制.1.什么是cookiecooki ...
- 分布式任务分发框架Gearman教程和PHP实现实例
1.Gearman介绍和使用场景 Gearman是一个分发任务的程序框架,可以用在各种场合,与Hadoop相 比,Gearman更偏向于任务分发功能.它的任务分布非常简单,简单得可以只需要用脚本即可完 ...
- Scanner概述
* Scanner:用于接收键盘录入数据. * System类下有一个静态的字段: * public static final InputStream in; 标准的输入流,对应着键盘录入. * * ...
- linux下开启mysql慢查询,分析查询语句
一,为什么要开启这个查询呢? 数据库是很容易产生瓶颈的地方,现在Nosql大家讨论这么热,估计都被数据库搞郁闷了.mysql中最影响速度的就是那些查询非常慢的语句,这些慢的语句,可能是写的不够合理或者 ...
- php创建多级目录的两种方法
1.使用递归的思想 function mkdirs_2($path){ if(!is_dir($path)){ mkdirs_2(dirname($path)); if(!mkdir($path, 0 ...
- 异常:Message 850 not found; No message file for product=network, facility=NL解决方案
一.异常信息: Message 850 not found; No message file for product=network, facility=NL 二.解决方案: 后来在 ...
- RNN神经网络和英中机器翻译的实现
本文系qitta的文章翻译而成,由renzhe0009实现.转载请注明以上信息,谢谢合作. 本文主要讲解以recurrent neural network为主,以及使用Chainer和自然语言处理其中 ...
- 标清与高清,720p和1080p,720i和720p,h264与h265
480x320, 640x480 标清 1024x720p 高清 1920x1080i (隔行扫描) 也属于高清 1920x1080p 全高清 3840x2160,7680x4320 超(高)清 ...