http://docs.scala-lang.org/tour/lower-type-bounds.html中有一段代码

trait Node[+B] {def prepend(elem: B): Unit
}case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {def prepend(elem: B) = ListNode[B](elem, this)def head: B = hdef tail = t
}case class Nil[+B]() extends Node[B] {def prepend(elem: B) = ListNode[B](elem, this)
}

  文中说这段代码不会通过编译,因为Function1是contravariant 在参数的位置上。看到这里是一个头很多个大的。 However, this program does not compile because the parameter elem in prepend is of type B, which we declared covariant. This doesn’t work because functions are contravariant in their parameter types and covariant in their result types.

  先假设一下如果能编译通过的话。

  假设有这样子的一段代码

trait Animal
case class Dog() extends Animal
case class Cat() extends Animal
def addDogToAnimal(animalNode : ListNode[Animal]) : Unit{
    animalNode.prepend(Dog())
}

如果generic的类型是Animal的话,ListNode就变成如下case class ListNode[Animal](h: Animal, t: Node[Animal]) extends Node[Animal] {def prepend(elem: Animal) = ListNode[Animal](elem, this)def head: Animal = hdef tail = t
}
如果generic的类型是Cat的话,ListNode就变成如下case class ListNode[Cat](h:Cat, t: Node[Cat]) extends Node[Cat] {def prepend(elem:Cat) = ListNode[Cat](elem, this)def head: Cat= hdef tail = t
}

 addDogToAnimal方法接受一个ListNode[Animal],因为ListNode[Cat] 是 ListNode[Animal]的子类(因为是Covaraiance的)

 所以我们可以addDogToAnimal(ListNode(Cat(), Nil())),但是ListNode[Cat]只能prepend是Cat类型的对象。所以一定会出问题。

 解决方法就是在所有需要消费者方法中 introducing a new type parameter U that has B as a lower type bound.

trait Node[+B] { def prepend[U >: B](elem: U) } case class ListNode[+B](h: B, t: Node[B]) extends Node[B] { def prepend[U >: B](elem: U) = ListNode[U](elem, this) def head: B = h def tail = t } case class Nil[+B]() extends Node[B] { def prepend[U >: B](elem: U) = ListNode[U](elem, this) }现在再来看刚才的问题

如果generic的类型是Animal的话,ListNode就变成如下
case class ListNode[Animal](h: Animal, t: Node[Animal]) extends Node[Animal] {def prepend[U >: Animal](elem: Animal) = ListNode[Animal](elem, this)def head: Animal = hdef tail = t
}
如果generic的类型是Cat的话,ListNode就变成如下case class ListNode[Cat](h:Cat, t: Node[Cat]) extends Node[Cat] {def prepend[U >: Cat](elem:Cat) = ListNode[Cat](elem, this)def head: Cat= hdef tail = t
}
ListNode[Cat] 还是 ListNode[Animal]的子类addDogToAnimal(ListNode(Cat(), Nil()))的时候ListNode[Cat]的prepend方法可以接受所有U >: Cat 的对象所以prepend方法可以接受Animal的对象作为参数。Dog也是一种Animal,所以animalNode.prepend(Dog())是没有问题的在这里以一个java开发者来说,会觉得很不合理。明明是cat类型的ListNode,怎么可以加入dog。但这也是scala和java的不同呀。唉


  

转载于:https://www.cnblogs.com/robsann/p/7674918.html

Scala类型系统(sudden thought)相关推荐

  1. Scala类型系统的目的——Martin Odersky访谈(三)

    Martin Odersky向Frank Sommers和Bill Venners谈论Scala类型系统背后的设计动机. \\ Scala是一种新兴的通用用途.类型安全的Java平台语言,结合了面向对 ...

  2. Scala类型系统——高级类类型(higher-kinded types)

    高级类类型就是使用其他类型构造成为一个新的类型,因此也称为 类型构造器(type constructors).它的语法和高阶函数(higher-order functions)相似,高阶函数就是将其它 ...

  3. scala类型系统之: 类型变量界定、视图界定、上下文界定

    类型变量界定(Type Variable Bound).视图界定(View Bound).上下文界定(Context Bound),在scala中算很重要的内容了,这次博客就来写点自己的理解. 1.类 ...

  4. Scala模式匹配的亮点——Martin Odersky访谈(四)

    Martin Odersky向Bill Venners和Frank Sommers谈论Scala模式匹配的机制和目的. \\ Scala是一种新兴的通用用途.类型安全的Java平台语言,结合了面向对象 ...

  5. Scala入门到精通——第二十四节 高级类型 (三)

    本节主要内容 Type Specialization Manifest.TypeTag.ClassTag Scala类型系统总结 在Scala中,类(class)与类型(type)是两个不一样的概念. ...

  6. 可扩展的编程语言——Scala

    一.Scala是什么 Scala是一种多范式的编程语言,其设计的初衷是要集成面向对象编程和函数式编程的各种特性.Scala运行于Java平台(Java虚拟机),并兼容现有的Java程序. ​ Scal ...

  7. scala 基础十一 scala 中的trait特质

    1.Scala类型系统的基础部分是与Java非常相像的.Scala与Java一样有单一的根类,Java通过接口来实现多重继承,而Scala则通过特征(trait)来实现(Scala的特征可以包含实现代 ...

  8. scala面试题简要总结

    scala介绍一下 scala运行在java虚拟机上 scala同时支持面向对象与函数式编程 scala的代码比java的代码更加精简 scala目前主要应用在spark开发 关于scala,你有什么 ...

  9. Effective Scala

    Marius Eriksen, Twitter Inc. marius@twitter.com (@marius) [translated by hongjiang(@hongjiang), tong ...

最新文章

  1. C++语言基础 例程 文本文件的读写
  2. 磁盘格式化,磁盘挂载,手动增加swap空间
  3. [Stardust]星尘分布式全链路监控
  4. 线程同步有几种方法_架构师面试必问的多线程状态切换及常用方法
  5. monit监控mysql_monit监控工具(客户端)
  6. HoloLens 2开发:三种工程部署方式
  7. Codeforces Round #468 (Div. 2): C. Laboratory Work(贪心)
  8. 喜欢使用VMware的.net程序员要注意呀(Visual Studio启动不了的问题)
  9. 2n个数的中位数问题_python_算法与数据结构
  10. [转]Java计时器Timer 使用
  11. java sha加密算法_Java加密 消息摘要算法SHA实现详解
  12. axios基于常见业务场景的二次封装
  13. sprutcam 多机器人_Sprutcam工业机器人离线编程系统
  14. PCB板设计流程有哪些?
  15. code 128 字体扫描不可识别
  16. 泊松回归模型matlab,matlab拟合泊松分布
  17. cd linux 镜像,解开 CDLinux 的iso映像文件
  18. c# .net对接企业微信小助手 接口请求时长预警
  19. 电脑开启后,进入桌面黑屏,任务管理器可以用(排除是硬件问题)
  20. OpenFPGA 环境配置及问题解决

热门文章

  1. php如何计算精确,简单谈谈php浮点数精确运算
  2. javascript 语言国际化
  3. iphone 开发安装环境
  4. html事件中写js,html标签中绑定触发事件与js中绑定触发事件写法上的区别
  5. flink checkpoint 恢复_Apache Flink 管理大型状态之增量 Checkpoint 详解
  6. hash算法_阿里面试官:讲一下Hashmap中hash算法!
  7. 2020-02-09 改udev硬件配置策略,改ETHTOOL_OPTS 或改 `/etc/NetworkManager/dispatcher.d/20-ethtool`...
  8. 国内少有的Flutter干货分享:Flutter的原理及美团的实践!
  9. cocos2dx 2.0升级为3.0一些常见变化纪录
  10. java 动态给属性赋值_java中为实体对象的动态属性赋值