[Scala] 了解 协变 与 逆变
首先定义一个类 A,其参数类型 T 为协变,类中包含一个方法 func,该方法有一个类型为 T 的参数:
- class A[+T] {
- def func(x: T) {}
- }
此时在 x 处会有异常提示,covariant type T occurs in contravariant position in type T of value x
- val father: A[AnyRef] = null.asInstanceOf[A[AnyRef]] // 父类对象,包含方法 func(x: AnyRef)
- val child: A[String] = null.asInstanceOf[A[String]] // 子类对象,包含方法 func(x: String)
- def otherFunc(x: A[AnyRef]): Unit = {
- x.func(Nil)
- }

- val fatherFather: A[Any] = null.asInstanceOf[A[Any]] // func(x: Any)
- otherFunc(fatherFather)// 如果 T 为协变,此处会提示异常
总结:
- 如果将 T 作为 func 方法的返回值类型,即处于协变点,就可以编译通过。
- class B[+T] {
- def func(): T = {
- null.asInstanceOf[T]
- }
- }
- // 与 Function0[+A] 等价
- 或者将类型参数 T 改为逆变,
- class A[-T] {
- def func(x: T) {}
- }
- // 与 Function1[-A, Unit] 等价
- val father: A[AnyRef] = null.asInstanceOf[A[AnyRef]] // func(x: AnyRef)
- val fatherFather: A[Any] = null.asInstanceOf[A[Any]] // func(x: Any)
- def otherFunc(x: A[AnyRef]): Unit = {
- x.func(Nil)
- }
- otherFunc(father) // success
- otherFunc(fatherFather)// success
参考网址:
span::selection, .codemirror-line > span > span::selection { background: #d7d4f0; }.codemirror-line::-moz-selection, .codemirror-line > span::-moz-selection, .codemirror-line > span > span::-moz-selection { background: #d7d4f0; }.cm-searching {background: #ffa; background: rgba(255, 255, 0, .4);}.cm-force-border { padding-right: .1px; }@media print { .codemirror div.codemirror-cursors {visibility: hidden;}}.cm-tab-wrap-hack:after { content: ""; }span.codemirror-selectedtext { background: none; }.codemirror-activeline-background, .codemirror-selected {transition: visibility 0ms 100ms;}.codemirror-blur .codemirror-activeline-background, .codemirror-blur .codemirror-selected {visibility:hidden;}.codemirror-blur .codemirror-matchingbracket {color:inherit !important;outline:none !important;text-decoration:none !important;}
-->
li {list-style-type:decimal;}.wiz-editor-body ol.wiz-list-level2 > li {list-style-type:lower-latin;}.wiz-editor-body ol.wiz-list-level3 > li {list-style-type:lower-roman;}.wiz-editor-body blockquote {padding:0 12px;padding:0 0.75rem;}.wiz-editor-body blockquote > :first-child {margin-top:0;}.wiz-editor-body blockquote > :last-child {margin-bottom:0;}.wiz-editor-body img {border:0;max-width:100%;height:auto !important;margin:2px 0;}.wiz-editor-body table {border-collapse:collapse;border:1px solid #bbbbbb;}.wiz-editor-body td,.wiz-editor-body th {padding:4px 8px;border-collapse:collapse;border:1px solid #bbbbbb;min-height:28px;word-break:break-all;box-sizing: border-box;}.wiz-hide {display:none !important;}
-->
[Scala] 了解 协变 与 逆变的更多相关文章
- (转)Scala中协变(+)、逆变(-)、上界(<:)、下界(>:)简单介绍
看源码的时候看到: trait ExtensionId[T <: Extension] { 没见过这个符号啊<: Scala上界(<:)和下界(>:) 1) U >: T ...
- scala学习笔记-类型参数中协变(+)、逆变(-)、类型上界(<:)和类型下界(>:)的使用
转载自 fineqtbull http://fineqtbull.iteye.com/blog/477994 有位je上的同学来短信向我问起了Scala类型参数中协变.逆变.类型上界和类型下界的 ...
- Scala类型参数中协变(+)、逆变(-)、类型上界(<:)和类型下界(>:)的使用
转自:http://fineqtbull.iteye.com/blog/477994#bc2364938 有位je上的同学来短信向我问起了Scala类型参数中协变.逆变.类型上界和类型下界的使用方法和 ...
- Scala 基础(十六):泛型、类型约束-上界(Upper Bounds)/下界(lower bounds)、视图界定(View bounds)、上下文界定(Context bounds)、协变、逆变和不变
1 泛型 1)如果我们要求函数的参数可以接受任意类型.可以使用泛型,这个类型可以代表任意的数据类型. 2)例如 List,在创建 List 时,可以传入整型.字符串.浮点数等等任意类型.那是因为 Li ...
- Scala中的协变,逆变,上界,下界等
Scala中的协变,逆变,上界,下界等 目录 [−] Java中的协变和逆变 Scala的协变 Scala的逆变 下界lower bounds 上界upper bounds 综合协变,逆变,上界,下界 ...
- Scala教程之:深入理解协变和逆变
文章目录 函数的参数和返回值 可变类型的变异 在之前的文章中我们简单的介绍过scala中的协变和逆变,我们使用+ 来表示协变类型:使用-表示逆变类型:非转化类型不需要添加标记. 假如我们定义一个cla ...
- 不变(Invariant), 协变(Covarinat), 逆变(Contravariant) : 一个程序猿进化的故事
阿袁工作的第1天: 不变(Invariant), 协变(Covarinat), 逆变(Contravariant)的初次约 阿袁,早!开始工作吧. 阿袁在笔记上写下今天工作清单: 实现一个scala类 ...
- 从底层实现剖析Kotlin协变与逆变的原理
继续还是探究协变与逆变,在正式开始之前,先来对Kotlin和Java的协变与逆变进行一个对比: 1.Kotlin是声明处协变:而在Java中是在使用处协变: 如何理解,我们先来回顾一下在Java使用协 ...
- C#4.0泛型的协变,逆变深入剖析
C#4.0中有一个新特性:协变与逆变.可能很多人在开发过程中不常用到,但是深入的了解他们,肯定是有好处的. 协变和逆变体现在泛型的接口和委托上面,也就是对泛型参数的声明,可以声明为协变,或者逆变.什么 ...
随机推荐
- linux2.6硬盘扇区直接读写程序
下面的程序可以在linux2.6内核直接读写硬盘的指定扇区,也是根据网上一个朋友的做法做了修改的: 有两个不是很明白的地方就是:1.bd_claim函数的使用,这个是个递归函数,像是匹配内存指针和设备 ...
- Python 第二天学习(文件的处理)
学习的内容是: python的文件处理 列表,元组,字典的使用 集合的使用 函数 文件file.textd的内容 A person with high EQ doesn't often critici ...
- MyEclipse开发平台下如何将新建的JSP页面的默认编码格式设置为UTF-8--JSP
新建的JSP页面原始的编码格式是ISO-8859-1(测试的MyEclipse版本为2014),它是不支持中文,在预览JSP页面时会出现乱码的现象.当然自己手动改一下编码格式就好了,但是那太过麻烦,每 ...
- Keras FAQ: 常见问题解答
Keras官方中文版文档 如何引用 Keras? 如何在 GPU 上运行 Keras? 如何在多 GPU 上运行 Keras 模型? "sample", "batch&q ...
- AndroidStudio 集成litepal 报错
E/AndroidRuntime(24972): org.litepal.c.b: can not find a class named org.litepal.model.Table_Schema ...
- 【BZOJ1857】传送带(三分)
[BZOJ1857]传送带(三分) 题面 Description 在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段.两条传送带分别为线段AB和线段CD.lxhgww在AB上的移动速度为P, ...
- Bzoj4872: [Shoi2017]分手是祝愿
题面 Bzoj Sol 首先从大向小,能关就关显然是最优 然后 设\(f[i]\)表示剩下最优要按i个开关的期望步数,倒推过来就是 \[ f[i]=f[i-1]*i*inv[n]+f[i+1]*(n- ...
- linux优化项
Linux优化: 1.建立普通账号,使用普通用户登陆. 2.处理SELINUX. 3.处理防火墙. 4.精简开机自启动服务.保留sshd,network,crond,rsyslog,sysstat. ...
- Cocos2d-x 集成openinstall(Android)
目的: 1. Cocos2d-x集成openinstall sdk? 有这么一个场景,甲给乙分享了链接,乙使用并下载APP,推荐者甲和乙的关系这个思路是怎样的? 你首先想到的也许会说,那当然就是给对方 ...
- DataX通过纯Java代码启动
DataX是阿里巴巴团队开发的一个很好开源项目,但是他们对如何使用只提供了python命令启动方式,这种方式对于只是想简单的用下DataX的人来说很是友好,仅仅需要几行代码就可以运行,但是如果你需要在 ...