一.本章要点

  • 类、特质、方法和函数都可以有类型参数
  • 将类型参数放置在名称之后,以方括号括起来
  • 类型界定的语法为T<:UpperBound、T>:LowerBound、T<%ViewBound、T:ContextBound
  • 可以用类型约束来约束一个方法,比如(implicit ev:T<:<UpperBound)
  • 用+T(协变来表示某个泛型的子类型关系和参数T方向一致,或用-T(逆变)来表示方向相反
  • 协变适用于表示输出的类型参数,比如不可表集合中的元素
  • 逆变适用于表示输入的类型参数,比如函数参数

二.泛型类

  和Java/C++一致,类和特质都可以带类型参数。在类的定义中,可以用类型参数来定义变量、方法参数、以及返回值类型。例:

class Pair[T,S]{val first:T,val secend:S}

三.泛型函数

  函数和方法也可以带类型参数。例:

def getMiddle[T](a:Array[T])=a(a.length/2)

四.类型变量界定

  对类型变量进行限制,例:

//错误
class Pair[T](val first:T,val secend:T)
//不知道first是否有compareTo方法
{def smaller=if(first.compareTo(secend)<0) first else secend
} //解决方法(比较简单,也可以指定一个下界)
class Pair[T<:Comparable[T]](val first:T,val secend:T){
def smaller=if(first.compareTo(secend)<0) first else secend
}  
  

五.视图界定

  ”视图界定“,T<%V要求必须存在一个从T到V的隐式转换,如class Pair[T <% Comparable[T]],<%意味着T可以被隐式转换成Comparable[T]。。。          

六.上下文界定

  格式为T:M,其中M是一个泛型类,要求必须存在一个类型为M[T]的”隐式值“。

    

七.Manifest上下文界定

  要实例化一个泛型的Array[T],需要一个Mainfest[T]对象(要想让基本类型的数组能工作,这是必须的),例:

def makePair(T:Mainfest)(first:T,secend:T){
val r=new Array[T](2);r(0)=first;r(1)=secend;r
}

  注:如果T是Int,希望虚拟机中对应的是一个int[]数组,在Scala中,Array只不过是类库中提供的一个类,编译器并不对它做特殊处理,因此要编写一个泛型函数来构造泛型数组,需要传入Mainfest对象帮忙(因为在虚拟机中,泛型相关的信息是被抹掉的,只会有一个makePair方法,却要处理所有类型T)。

八.多重界定

  类型变量可以同时有上界和下界,写法为T >:Lower <:Upper,不能同时有多个上界或多个下界,但能同时实现多个特质。

  可以有多个视图特质:T%<Comparable[T]<%String

  可以有多个上下文界定:T:Ordering:Mainfest

九.类型约束

  提供的另一种限定类型的方式,总共有三种关系:

    T=:=U

    T<:<U

    T<%<U

  这些约束将会测试T是否等于U,是否是U的子类型,或是否能被视图(隐式)转换为U,要使用这样的约束,需要添加”隐式类型证明参数“。  

  类型参数可在泛型类中定义只能在特定条件下使用的方法,例:

class Pair[T](val first:T,val second:T){
def smaller(implicit ev:T<:<Ordered[T])=
if(first<second) first else second
}

  类型约束的另一个用途是改进类型推断,例:

def firstLast[A,C<:Iterable[A](it:C)=(it.head,it.last)]

//执行,推断出的类型参数[Nothing,List[Int]]不符合[A,C<:Iterable[A]]
firstLast(List(1,2,3))  

十.型变

  例:

def makeFriends(p:Pair[Person])
//如果用Pair[Student]作为参数调用makeFriends在缺省情况下是错误的,尽管Student是Person的子类,但Pair[Student]和Pair[Person]没有任何关系 //想要这样的关系,必须在Pair类中表明
//+号意味着该类型是T协变的(与T按同样的类型型变),即Student是Person的子类型=》Pait[Student]是Pair[Person]的子类型
class Pair[+T](val first:T,val second:T) //另一个方向的型变
trait Friend[-T]{
def befriend(someone:T)}
//可以是逆变的,Student是Person的子类型,Friend[Student]是Friend[Person]的超类型
class Person extends Friends[Person]
class Student extends Person
val susan=new Student
val fred=new Person
makeFriendWith(susan,fred)
//注:在一个泛型的类型声明里面,可以同时使用这两种型变

十一.协变和逆变点

  通常而言,对于某个对象消费的值适用于逆变,而对于它产出的值则适用于协变。

  在Scala中数组是不支持型变的,不能将Array[Student]转换为Array[Person],或者反过来会不安全。。。        

十二.对象不能泛型

  没法给对象添加类型参数,比如可变列表。。。

十三.类型通配符

  在Java中,所有泛型类都是不可变的,可以使用通配符改变它们的类型。

  可以在Scala中使用通配符。。。  

十四.练习

Scala学习十七——类型参数的更多相关文章

  1. scala学习笔记-类型参数中协变(+)、逆变(-)、类型上界(<:)和类型下界(>:)的使用

    转载自  fineqtbull   http://fineqtbull.iteye.com/blog/477994 有位je上的同学来短信向我问起了Scala类型参数中协变.逆变.类型上界和类型下界的 ...

  2. Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、

    1:Scala和Java的对比: 1.1:Scala中的函数是Java中完全没有的概念.因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象,而且只 ...

  3. 入门大数据---Scala学习

    Scala是什么? Scala是一种基于函数式编程和面向对象的高级语言.它开发了Spark等大型应用.它和Java有效集成,底层也是支持JVM的. 它有六大特性: 无缝JAVA互操作 Scala在JV ...

  4. Scala学习资源

    Scala学习资源: Scala官方网站:http://www.scala-lang.org/ Scala github:https://github.com/scala/scala Twitter ...

  5. 【Todo】【读书笔记】大数据Spark企业级实战版 & Scala学习

    下了这本<大数据Spark企业级实战版>, 另外还有一本<Spark大数据处理:技术.应用与性能优化(全)> 先看前一篇. 根据书里的前言里面,对于阅读顺序的建议.先看最后的S ...

  6. 机器学习(三)--- scala学习笔记

    Scala是一门多范式的编程语言,一种类似Java的编程语言,设计初衷是实现可伸缩的语言.并集成面向对象编程和函数式编程的各种特性. Spark是UC Berkeley AMP lab所开源的类Had ...

  7. 【Scala】Scala学习资料

    Scala学习资料 java 树形 分类器_百度搜索 决策树分类器-Java实现 - CSDN博客 KNN分类器-Java实现 - CSDN博客 学习:java设计模式—分类 - 飞翔荷兰人 - 博客 ...

  8. Scala学习网址

    scala学习网址为:https://twitter.github.io/scala_school/zh_cn https://www.zhihu.com/question/26707124

  9. Spark之Scala学习

    1. Scala集合学习: http://blog.csdn.net/lyrebing/article/details/20362227 2. scala实现kmeans算法 http://www.t ...

随机推荐

  1. 7 AOP

    AOP:Aspect Oriented Programming 面向切面编程.AOP是对面向对象编程的一种补充,在运行时动态地将代码切入到类的指定方法.指定位置的编程思想.将不同的方法的同一位置抽象成 ...

  2. linux系统安装Memcache

    Linux系统安装memcached 首先要先安装libevent库. centos  下执行 yum install libevent libevent-devel 查看memcached 是否已经 ...

  3. jquery - 定义二维数组

    var products = []; products.push({product_id: '1',count: 3},{product_id:'2',count: 6})

  4. SQL-W3School-高级:SQL VIEW(视图)

    ylbtech-SQL-W3School-高级:SQL VIEW(视图) 1.返回顶部 1. 视图是可视化的表. 本章讲解如何创建.更新和删除视图. SQL CREATE VIEW 语句 什么是视图? ...

  5. ubuntu 命令行以及目录的显示改为英文

    在安装ubuntu的时候原本以为把ubuntu改为中文的好理解一些,最后发现命令行的报错一边中文一边英文确实难受,也不宜于学习,所以想把命令行以及目录的显示都改为英文的,我是这样先把命令行的该为英文的 ...

  6. 图解 HTTP 笔记(三)—— HTTP 报文内的 HTTP 信息

    本章主要讲解请求和响应是如何运作的 一.HTTP 报文 用于 HTTP 协议交互的信息被称为 HTTP 报文,客户端的 HTTP 报文叫做请求报文,服务器端的叫做响应报文. HTTP 报文大致可分为报 ...

  7. Spring Boot项目中MyBatis连接DB2和MySQL数据库返回结果中一些字符消失——debug笔记

    写这篇记录的原因是因为我之前在Spring Boot项目中通过MyBatis连接DB2返回的结果中存在一些字段, 这些字段的元素中缺少了一些符号,所以我现在通过在自己的电脑上通过MyBatis连接DB ...

  8. linux LVM 系统盘扩容

    1.fdisk /dev/sda2.输入n,开始创建新分区3.输入p4.输入w5.mkfs.ext4 /dev/sda36.pvcreate /dev/sda37.vgdisplay 查看VG nam ...

  9. 攻防世界WEB新手练习

    0x01 view_source 0x02 get_post 这道题就是最基础的get和post请求的发送 flag:cyberpeace{b1e763710ff23f2acf16c2358d3132 ...

  10. HDU6582 Path【优先队列优化最短路 + dinic最大流 == 最小割】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582 来源:2019 Multi-University Training Contest 1 题目大意 ...