Scala学习十七——类型参数
一.本章要点
- 类、特质、方法和函数都可以有类型参数
- 将类型参数放置在名称之后,以方括号括起来
- 类型界定的语法为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学习十七——类型参数的更多相关文章
- scala学习笔记-类型参数中协变(+)、逆变(-)、类型上界(<:)和类型下界(>:)的使用
转载自 fineqtbull http://fineqtbull.iteye.com/blog/477994 有位je上的同学来短信向我问起了Scala类型参数中协变.逆变.类型上界和类型下界的 ...
- Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、
1:Scala和Java的对比: 1.1:Scala中的函数是Java中完全没有的概念.因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象,而且只 ...
- 入门大数据---Scala学习
Scala是什么? Scala是一种基于函数式编程和面向对象的高级语言.它开发了Spark等大型应用.它和Java有效集成,底层也是支持JVM的. 它有六大特性: 无缝JAVA互操作 Scala在JV ...
- Scala学习资源
Scala学习资源: Scala官方网站:http://www.scala-lang.org/ Scala github:https://github.com/scala/scala Twitter ...
- 【Todo】【读书笔记】大数据Spark企业级实战版 & Scala学习
下了这本<大数据Spark企业级实战版>, 另外还有一本<Spark大数据处理:技术.应用与性能优化(全)> 先看前一篇. 根据书里的前言里面,对于阅读顺序的建议.先看最后的S ...
- 机器学习(三)--- scala学习笔记
Scala是一门多范式的编程语言,一种类似Java的编程语言,设计初衷是实现可伸缩的语言.并集成面向对象编程和函数式编程的各种特性. Spark是UC Berkeley AMP lab所开源的类Had ...
- 【Scala】Scala学习资料
Scala学习资料 java 树形 分类器_百度搜索 决策树分类器-Java实现 - CSDN博客 KNN分类器-Java实现 - CSDN博客 学习:java设计模式—分类 - 飞翔荷兰人 - 博客 ...
- Scala学习网址
scala学习网址为:https://twitter.github.io/scala_school/zh_cn https://www.zhihu.com/question/26707124
- Spark之Scala学习
1. Scala集合学习: http://blog.csdn.net/lyrebing/article/details/20362227 2. scala实现kmeans算法 http://www.t ...
随机推荐
- vue props传值后watch事件未触发的问题
父组件传值,子组件监听,明明很简单的一个事情,硬是卡了许久(毕竟不是专业搞前端的,还是吃亏在学识浅陋).也和自己钻牛角尖有关,想自己解决问题. 早期我写过一篇vue组件传值的文章,传值方式是这样的: ...
- Maven的几种新建项目方式
1. 使用原型创建Maven的java工程 (1) 选择 JDK 的版本,勾选“使用原型创建”,选中 maven-archetype-quickstart,下一步. (2) 填写公司名,填写项目名,修 ...
- java跨域配置
一.问题 使用前后端分离模式开发项目时,往往会遇到这样一个问题 -- 无法跨域获取服务端数据 这是由于浏览器的同源策略导致的,目的是为了安全.在前后端分离开发模式备受青睐的今天,前端和后台项目往往会在 ...
- linux设置脚本开机自启
由于在centos7中/etc/rc.d/rc.local的权限被降低了,所以需要赋予其可执行权 chmod +x /etc/rc.d/rc.local 赋予脚本可执行权限假设/opt/script/ ...
- 【Java/JDBC】借助ResultSetMetaData,从数据库表中抽取字段信息存成Excel文件
本例工程下载:https://files.cnblogs.com/files/xiandedanteng/FindNotnullColumns20191102-3.rar 工作中曾有个为42张表建立测 ...
- C之指针
什么是指针 * 指针变量:用来存储某种数据在内存中的地址.* 世面上书籍一般把指针和指针变量的概念混在一起了.市面上的书籍说的指针指的就是指针变量 Ø *号的三种含义1. 两个数相乘int i =5; ...
- 浅谈smarty模板的mvc框架
最近接触了一个大项目,php做的后台管理,融合了smarty模板+mvc框架+phpcms内容管理,,,这个项目简直就是php的精华,于是小编大哥对项目小女子产生了兴趣,打算一点一点把她征服.现在小吃 ...
- 在IIS7、IIS7.5中应用程序池最优配置方案
先介绍几个简单的设置 应用程序池 > 高级设置 1.基本设置 队列长度: 65535 启动32位应用程序 否则安装一些32的组建或32位的php都会出错 托管管道模式 Classsic 2.高级 ...
- Goland 激活码
实测有效,分享下 Goland
- linux中环境变量设置
Linux下环境变量设置的三种方法: 如想将一个路径加入到$PATH中,可以像下面这样做: 只对当前的shell 起作用的环境变量 1.控制台中设置,不赞成这种方式,因为他只对当前的shell 起作用 ...