scala当中的类型参数
类型参数主要就是研究scala当中的类或者scala当中的方法的泛型
1、scala当中的类的泛型
|
object Demo8 { def main(args: Array[String]): Unit = { val result1 = new MyClass("hello",50) val result2 = new MyClass[Any,Any]("zhangsan","Lisi"); } } /** * 定义一个class类,接收两个参数,但是两个参数都是泛型,泛型的类型,会根据我们 * 创建类的实例化对象的时候,动态的传递进行动态的推断 * @param first * @param second * @tparam T * @tparam B */ class MyClass[T,B](first:T,second:B){ println(first+","+second) } |
2、函数的泛型
我们的函数或者方法,也可以有类型参数
|
object methodType{ def getMiddle[T](canshu:T) ={ canshu } def main(args: Array[String]): Unit = { // 从参数类型来推断类型 println(getMiddle(Array("Bob", "had", "a", "little", "brother")).getClass.getTypeName) //指定类型,并保存为具体的函数。 val f = getMiddle[String] _ println(f("Bob")) } |
3、scala当中的上下界之泛型类型的限定
在scala当中,我们可以通过上界或者下界来限定我们泛型的类型,类似于java当中的
? extends T ?号就表示我们使用的泛型,必须是T类型的子类,这种情况叫做上界
? super T ?号就表示我们使用的泛型,必须是T类型的父类,这种情况叫做下界
在scala当中上界的表示方法使用的是 "<:", 这个符号就是表示上界,这种形式称之为泛型的上界。
在scala当中下界的表示方式使用的是 ">:", 这个符号就是表示下界,这种形式称之为泛型的下界
3.1、泛型的上界限定
我们可以通过上界的限定,限定我们传入的类型必须是某个类型的子类
|
class Pair1[T <: Comparable[T]](val first: T, val second: T) { def smaller = if (first.compareTo(second) < 0) first else second } object Main1 extends App{ override def main(args: Array[String]): Unit = { val p = new Pair1("hello", "Brooks") println(p.smaller) } } |
3.2、泛型的下界限定
我们可以通过下界的限定,限定我们传入的类型必须是某个类型的父类
|
class Pair2[T](val first: T, val second: T) { def replaceFirst[R >: T](newFirst: R) = new Pair2[R](newFirst, second) override def toString = "(" + first + "," + second + ")" } object Main2 extends App{ override def main(args: Array[String]): Unit = { val p = new Pair2("Nick", "Alice") println(p) println(p.replaceFirst("Joke")) println(p) } } |
在Java中,T同时是A和B的子类型,称之为多界,形式如:<T extends A & B>。
在Scala中,对上界和下界不能有多个,但是可以使用混合类型,如:[T <: A with B]。
在Java中,不支持下界的多界形式。如:<T super A & B>这是不支持的。
在Scala中,对复合类型依然可以使用下界,如:[T >: A with B]。
4、scala当中的视图界定
说白了就是将我们的泛型转化成了具体的类型
在Scala中,如果你想标记某一个泛型可以隐式的转换为另一个泛型,可以使用:[T <% Comparable[T]],由于Scala的Int类型没有实现Comparable接口,所以我们需要将Int类型隐式的转换为RichInt类型,比如:
我们如果需要比较两个值的大小,那么我们的两个值必须是Comparable的子类,那么我们可以使用泛型 T <% Comparable 来限制我们泛型必须是Comparable的子类,并且我们的泛型在执行真正比较的方法的时候,会根据我们传入的类型,自动推断,进行隐式的转换,例如我们传入4,2 进行比较,那么我们会将4, 2 这两个类型做自动推断,转换成真正的RichInt类型然后再继续进行比较
|
/** * 使用 <% 来实现我们类型的隐式转换 * @param first * @param second * @tparam T */ class Pair3[T <% Comparable[T]](val first: T, val second: T) { def smaller = if (first.compareTo(second) < 0) first else second override def toString = "(" + first + "," + second + ")" } object Main3 extends App { val p = new Pair3(4, 2) println(p.smaller) } |
5、scala当中的协变,逆变和非变
协变和逆变主要是用来解决参数化类型的泛化问题。Scala的协变与逆变是非常有特色的,完全解决了Java中泛型的一大缺憾;举例来说,Java中,如果有 A是 B的子类,但 Card[A] 却不是 Card[B] 的子类;而 Scala 中,只要灵活使用协变与逆变,就可以解决此类 Java 泛型问题;
由于参数化类型的参数(参数类型)是可变的,当两个参数化类型的参数是继承关系(可泛化),那被参数化的类型是否也可以泛化呢?Java中这种情况下是不可泛化的,然而Scala提供了三个选择,即协变("+")、逆变("-")和非变。
下面说一下三种情况的含义,首先假设有参数化特征Queue,那它可以有如下三种定义。
- trait Queue[T] {}
这是非变情况。这种情况下,当类型B是类型A的子类型,则Queue[B]与Queue[A]没有任何从属关系,这种情况是和Java一样的。
- trait Queue[+T] {}
这是协变情况。这种情况下,当类型B是类型A的子类型,则Queue[B]也可以认为是Queue[A]的子类型,即Queue[B]可以泛化为Queue[A]。也就是被参数化类型的泛化方向与参数类型的方向是一致的,所以称为协变。 - trait Queue[-T] {}
这是逆变情况。这种情况下,当类型B是类型A的子类型,则Queue[A]反过来可以认为是Queue[B]的子类型。也就是被参数化类型的泛化方向与参数类型的方向是相反的,所以称为逆变。
协变、逆变、非变总结
- C[+T]:如果A是B的子类,那么C[A]是C[B]的子类。
- C[-T]:如果A是B的子类,那么C[B]是C[A]的子类。
- C[T]: 无论A和B是什么关系,C[A]和C[B]没有从属关系。
案例
|
package com.starzy.scala class Super class Sub extends Super //协变 class Temp1[+A](title: String) //逆变 class Temp2[-A](title: String) //非变 class Temp3[A](title: String) object Covariance_demo{ def main(args: Array[String]) { //支持协变 Temp1[Sub]还是Temp1[Super]的子类 val t1: Temp1[Super] = new Temp1[Sub]("hello scala!!!") //支持逆变 Temp1[Super]是Temp1[Sub]的子类 val t2: Temp2[Sub] = new Temp2[Super]("hello scala!!!") //支持非变 Temp3[Super]与Temp3[Sub]没有从属关系,如下代码会报错 //val t3: Temp3[Sub] = new Temp3[Super]("hello scala!!!") //val t4: Temp3[Super] = new Temp3[Sub]("hello scala!!!") println(t1.toString) println(t2.toString) } } |
scala当中的类型参数的更多相关文章
- scala当中的文件操作和网络请求
1.读取文件当中每一行的数据 def main(args: Array[String]): Unit = { //注意文件的编码格式,如果编码格式不对,那么读取报错 val file: Buffere ...
- scala当中的对象
1.scala当中的Object 在scala当中,没有类似于像java当中的static修饰的静态属性或者静态方法或者静态代码块之类的,但是我们可以通过scala当中的Object来实现类似的功能. ...
- scala当中的类
1.类的定义与创建 创建一个scala class来定义我们的一个类.类当中可以定义各种属性或者方法,或者函数都可以 class Person { //定义一个属性,叫做name的 ...
- scala学习笔记-类型参数中协变(+)、逆变(-)、类型上界(<:)和类型下界(>:)的使用
转载自 fineqtbull http://fineqtbull.iteye.com/blog/477994 有位je上的同学来短信向我问起了Scala类型参数中协变.逆变.类型上界和类型下界的 ...
- scala当中的Actor并发编程
注:Scala Actor是scala 2.10.x版本及以前版本的Actor. Scala在2.11.x版本中将Akka加入其中,作为其默认的Actor,老版本的Actor已经废弃. 1.什么是Sc ...
- Scala学习十七——类型参数
一.本章要点 类.特质.方法和函数都可以有类型参数 将类型参数放置在名称之后,以方括号括起来 类型界定的语法为T<:UpperBound.T>:LowerBound.T<%ViewB ...
- scala当中的特质trait
1.将trait作为接口使用 Scala中的trait是一种特殊的概念: 首先先将trait作为接口使用,此时的trait就与Java中的接口 (interface)非常类似: 在trait中可以定义 ...
- scala当中的继承
1.Scala中继承(extends)的概念 Scala 中,让子类继承父类,与 Java 一样,也是使用 extends 关键字: 继承就代表,子类可继承父类的 field 和 method ,然后 ...
- Scala当中parallelize并行化的用法
[学习笔记] parallelize并行化集合是根据一个已经存在的Scala集合创建的RDD对象.集合的里面的元素将会被拷贝进入新创建出的一个可被并行操作的分布式数据集.例如:val rdd03 = ...
随机推荐
- IE7,8纯css实现圆角效果
众所周知,IE7,8不支持border-radius效果.但我们同样有办法用css实现这个效果,方法就是用border来模拟. <!DOCTYPE html> <html lang= ...
- HTTPS 使用成本
HTTPS 目前唯一的问题就是它还没有得到大规模应用,受到的关注和研究都比较少.至于使用成本和额外开销,完全不用太过担心. 一般来讲,使用 HTTPS 前大家可能会非常关注如下问题: 证书费用以及更新 ...
- spark2.4+elasticsearch6.1.1搭建一个推荐系统
目录 整体框架 安装相关的组件 elasticsearch安装 spark安装 下载es-hadoop中间件 安装计算向量相似度的elasticsearch插件 运行 结果展示 参考博客 本博文详细记 ...
- [转]log4net 发布到生产环境不写日志的解决方法--使用 NLog日志
本文转自:http://www.cnblogs.com/weiweictgu/p/5848805.html 1.升级到log4net的最新版 PM下执行 Install-Package log4net ...
- C# 之VS程序打包
VS2012没有自带打包工具,所以要先下载并安装一个打包工具.我采用微软提供的打包工具: InstallShield2015LimitedEdition.下载地址:http://pan.baidu. ...
- winform从table1获取需要的数据转存储到table2中
小技术一个,记录一下 ,以下记录的是用两种方式来实现,数据表的转移 table转存数据之前首先要明确两个函数: Add():是指在最后一行添加一行 InsertAt():可以插入到表中的指定行 需求: ...
- C/C++:Windows cmd 指令
一.快捷键1. Windows键 自从104键盘首次加入Windows键后,微软便一直计划为这个键添加更多功能,当然Win8也不例外. * Win+C:调出应用Charm菜单(Metro.传统桌面) ...
- BigDecimal 类的使用
BigDecimal 类的使用 1.使用 BigDecimal 的原因 由于需要计算金额,所有需要高精度计算,所有需要使用 BigDecimal 类. BigDecimal能够精确的表示一个小数, ...
- java核心技术-IO
一 .IO 1.1 流的简单介绍和分类 Java流操作的相关的类和接口: Java流类图结构: 四个抽象基类分别为:InputStream .OutputStream .Reader .Writer: ...
- Thymeleaf学习记录(2)--自动编译设置
了方便每次修改HTML文件都能实时刷新,做一下更改. 在application.properties文件加入以下命令: #thymeleaf start spring.thymeleaf.mode=H ...