一.本章要点

  • 类、特质、方法和函数都可以有类型参数
  • 将类型参数放置在名称之后,以方括号括起来
  • 类型界定的语法为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. 创建createElement

    let oDiv = { tag:'div',  props:{ id:'box' } }:   let oP = createElement('p',{'class':'list'},['周一']) ...

  2. 常见Web攻击及解决方案

    DoS和DDoS攻击 DoS(Denial of Service),即拒绝服务,造成远程服务器拒绝服务的行为被称为DoS攻击.其目的是使计算机或网络无法提供正常的服务.最常见的DoS攻击有计算机网络带 ...

  3. hey is a tiny program that sends some load to a web application.

    hey is a tiny program that sends some load to a web application. DOS attack DOS攻击生成 https://github.c ...

  4. Kotlin中反射

    枚举类成员 import kotlin.reflect.full.memberFunctions import kotlin.reflect.full.memberProperties fun mai ...

  5. HTM概述

    Html: Hyper Text Markup Language 超文本标记语言 超文本: 超出纯文本的范畴 标记语言: 标记其实就是标签 标签的格式: <标签名称>

  6. Access restriction: The type JPEGImageEncoder is not accessible due to restriction

    转: 解决办法:Access restriction: The type JPEGImageEncoder is not accessible due to restriction 2011年11月2 ...

  7. Qt编写自定义控件33-图片切换动画

    一.前言 在很多看图软件中,切换图片的时候可以带上动画过渡或者切换效果,显得更人性化,其实主要还是炫一些,比如百叶窗.透明度变化.左下角飞入等,无论多少种效果,核心都是围绕QPainter来进行,将各 ...

  8. 反射之深入理解Constructor原理

    .katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...

  9. mysql访问慢解决

    配置变更思路: 扩大MySQL连接数至2000,同时扩大操作系统最大文件描述符:扩大innodb缓存池 操作步骤: vi /etc/my.cnf max_connections = 2000innod ...

  10. python进阶-mock接口

    setting.py MYSQL_HOST='192.168.127.139' PASSWORD=' PORT=3306 USER='root' DB='stu' tools.py import py ...