编程知识 购物 网址 新闻 笑话 | 软件 日历 阅读 图书馆 China 头条阅读 学淘股 China Travel
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题 autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程 CSS/HTML/Xhtml html5 CSS XML/XSLT Dreamweaver教程 经验交流
站长资讯 .NET新手 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA VisualStudio ASP.NET-MVC .NET控件开发 EntityFramework WinRT-Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动 Html-Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP OracleERP DynamicsCRM K2 BPM 信息安全 企业信息 Android开发 iOS开发 WindowsPhone WindowsMobile 其他手机 敏捷开发 项目管理 软件工程 SQLServer Oracle MySQL NoSQL 其它数据库 Windows7 WindowsServer Linux
   -> Scala -> Scala类型系统(sudden thought) -> 正文阅读

[Scala]Scala类型系统(sudden thought)

  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 = h
  def 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 = h def 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= h def 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 = h
  def 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= h def 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的不同呀。唉





  
  Scala 最新文章
找出共同好友
Error when sending message to topic test
kafka 的 createDirectStream
Scala类型系统(sudden thought)
spark
R的两均值比较检验(非参数检验)
IDEA 中scala 程序运行时的错误:报错 test
为什么要创建开放源码的PlayScala社区?
scala学习手记36
play for scala 在模板中格式化Date
上一篇文章           查看所有文章
加:2017-10-16 23:24:25  更:2017-10-16 23:24:27 
 
360图书馆 软件开发资料 购物精选 新闻资讯 Chinese Culture 三丰软件 开发 中国文化 阅读网 头条阅读 学淘股 China Travel 日历 万年历 2020年2日历
2020-2-22 18:22:04
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  编程知识