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 学习: 逆变和协变的更多相关文章

  1. Scala 深入浅出实战经典 第81讲:Scala中List的构造是的类型约束逆变、协变、下界详解

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-97讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  2. Java 逆变与协变

    最近一直忙于学习模电.数电,搞得头晕脑胀,难得今天晚上挤出一些时间来分析一下Java中的逆变.协变.Java早于C#引入逆变.协变,两者在与C#稍有不同,Java中的逆变.协变引入早于C#,故在形式没 ...

  3. OOP中的逆变和协变

    逆变和协变在存在于强类型语言中,尽管非常少提及.可是里面蕴含了面向对象的世界观.感谢和我一起讨论这个问题的人. 这里用了C#.Scala的语法作为演示样例.事实上逆变和协变的概念跟语言本身关系不大.事 ...

  4. Java中的逆变与协变

    看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); ...

  5. C#4.0新特性(3):变性 Variance(逆变与协变)

    一句话总结:协变让一个粗粒度接口(或委托)可以接收一个更加具体的接口(或委托)作为参数(或返回值):逆变让一个接口(或委托)的参数类型(或返回值)类型更加具体化,也就是参数类型更强,更明确. 通常,协 ...

  6. Java中的逆变与协变(转)

    看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); ...

  7. Java 逆变与协变的名词说明

    最近在研究Thinking in Java的时候,感觉逆变与协变有点绕,特意整理一下,方便后人.我参考于Java中的逆变与协变,但是该作者整理的稍微有点过于概念化,我在这里简单的说一下 我对于协变于逆 ...

  8. C# 逆变与协变

    该文章中使用了较多的 委托delegate和Lambda表达式,如果你并不熟悉这些,请查看我的文章<委托与匿名委托>.<匿名委托与Lambda表达式>以便帮你建立完整的知识体系 ...

  9. .NET 4.0中的泛型逆变和协变

    转载自:http://www.cnblogs.com/Ninputer/archive/2008/11/22/generic_covariant.html:自己加了一些理解 随Visual Studi ...

随机推荐

  1. phpstorm的快捷键

    F5复制 F6移动 Alt + Delete键安全删除 Shift + F6重命名 按Ctrl + Alt + N内联变量 按Ctrl + Alt + M提取方法(Javascript的唯一) 按Ct ...

  2. 体验一下cygwin

    一直在windows下使用gvim,为了更方便的使用cscope.先是写了bat脚本,发现太不方便了. 于是想到了cygwin.下载安装工具就可以了进行默认安装了,配置比较简单. 调整包: ./set ...

  3. c#防止多次运行代码收集

    1.原文:经过我的测试,还比较好用,但是有个问题,如果不注销,用另一个用户进入,则程序不能判断出已运行.所以只限于用在单用户环境,还是不太完美. class Program { [STAThread] ...

  4. mysql事务,START TRANSACTION, COMMIT和ROLLBACK,SET AUTOCOMMIT语法

    http://yulei568.blog.163.com/blog/static/135886720071012444422/ MyISAM不支持 START TRANSACTION | BEGIN ...

  5. 037. asp.netWeb用户控件之五使用用户控件实现文件上传功能

    fileUpload.ascx代码: <%@ Control Language="C#" AutoEventWireup="true" CodeFile= ...

  6. Excel中如何提取字符串中的数字

    取字符串中的数字,假如数据在A列,提取公式为 =LOOKUP(9^9,--MID(A1,MIN(FIND({1,2,3,4,5,6,7,8,9,0},A1&5^19)),ROW($1:$99) ...

  7. Openstack Neutron DVR workflow

    目前在Juno版本的trunk中已经合入了DVR相关的代码,我的理解是在Juno版本中DVR是一个experimental feature.最好需要稳定一个版本以后再上生产环境.之前写过一篇博文是DV ...

  8. C# :GDI+技术生成复杂型彩色验证码(转载)

    该类是生成一个验证码的类,集合了网上大部分的C#关于GDI+的文章进行多次改进,现在已经形成了可在生产环节中使用的验证码. 该验证码加入了背景噪点,背景噪点曲线和直线,背景噪点文字以及扭曲,调暗,模糊 ...

  9. 全景VR视频外包公司:长年承接VR全景视频外包(技术分享YouTube的360全景视频)

    虽然比预期来得晚了些,但YouTube终于支持360度全景视频了,这应该会吸引不少VR(虚拟现实)爱好者.今年1月,Google就表示这一功能将在“接下来”的几周出现.现在YouTube上已经有了一些 ...

  10. Android无法收到指定广播的问题总结

    首先是应用中不能只有一个广播,必须有一个activity或者service(这种情况比较复杂参考http://www.cnblogs.com/welcoming/p/4120497.html) 简单的 ...