类型参数主要就是研究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,那它可以有如下三种定义。

  1. trait Queue[T] {}

    这是非变情况。这种情况下,当类型B是类型A的子类型,则Queue[B]与Queue[A]没有任何从属关系,这种情况是和Java一样的。

  2. trait Queue[+T] {} 
    这是协变情况。这种情况下,当类型B是类型A的子类型,则Queue[B]也可以认为是Queue[A]的子类型,即Queue[B]可以泛化为Queue[A]。也就是被参数化类型的泛化方向与参数类型的方向是一致的,所以称为协变。
  3.   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当中的类型参数的更多相关文章

  1. scala当中的文件操作和网络请求

    1.读取文件当中每一行的数据 def main(args: Array[String]): Unit = { //注意文件的编码格式,如果编码格式不对,那么读取报错 val file: Buffere ...

  2. scala当中的对象

    1.scala当中的Object 在scala当中,没有类似于像java当中的static修饰的静态属性或者静态方法或者静态代码块之类的,但是我们可以通过scala当中的Object来实现类似的功能. ...

  3. scala当中的类

    1.类的定义与创建 创建一个scala class来定义我们的一个类.类当中可以定义各种属性或者方法,或者函数都可以     class Person {       //定义一个属性,叫做name的 ...

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

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

  5. scala当中的Actor并发编程

    注:Scala Actor是scala 2.10.x版本及以前版本的Actor. Scala在2.11.x版本中将Akka加入其中,作为其默认的Actor,老版本的Actor已经废弃. 1.什么是Sc ...

  6. Scala学习十七——类型参数

    一.本章要点 类.特质.方法和函数都可以有类型参数 将类型参数放置在名称之后,以方括号括起来 类型界定的语法为T<:UpperBound.T>:LowerBound.T<%ViewB ...

  7. scala当中的特质trait

    1.将trait作为接口使用 Scala中的trait是一种特殊的概念: 首先先将trait作为接口使用,此时的trait就与Java中的接口 (interface)非常类似: 在trait中可以定义 ...

  8. scala当中的继承

    1.Scala中继承(extends)的概念 Scala 中,让子类继承父类,与 Java 一样,也是使用 extends 关键字: 继承就代表,子类可继承父类的 field 和 method ,然后 ...

  9. Scala当中parallelize并行化的用法

    [学习笔记] parallelize并行化集合是根据一个已经存在的Scala集合创建的RDD对象.集合的里面的元素将会被拷贝进入新创建出的一个可被并行操作的分布式数据集.例如:val rdd03 = ...

随机推荐

  1. dll ocx cab IE 自动安装

    我们打开淘宝等网站时,IE浏览器会提示安装空间,这个控件便是用于对用户名密码进行加密的ActiveX控件.如何在我们的站点上安装如此控件,让用户可以通过简单的点击便可方便使用我们的空间呢? 下面是如何 ...

  2. audio标签的自动播放(ios)

    0.应用场景 前端移动端开发,经常有播放音乐的需求.比如我有公司做过类似支付宝的年度账单,功能是用户在查看年度账单的过程中播放轻音乐. 1.audio标签播放mp3 (一)常用属性和API介绍 1.c ...

  3. html之内容解析

    首先我们知道了HTML和css用途,那么今天就来看看HTML的一部分功能和用途. 简单的说HTML就是灵活使用标签,标签就相当于一个网页的骨架,有了这个骨架才能使网页更能区域色彩化. 首先来说HTML ...

  4. 【原】jQuery easyUI 快速搭建前端框架

    jQueryEasyUI jQuery EasyUI是一组基于jQuery的UI插件集合体,而jQuery EasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面.开发者不需要 ...

  5. MYSQL DATE_FORMAT() 函数时间大小比较

    DATE_FORMAT() 函数用于以不同的格式显示日期/时间数据. DATE_FORMAT(date,format) 可以使用的格式有: 格式 描述 %a 缩写星期名 %b 缩写月名 %c 月,数值 ...

  6. iOS开发之工具篇-20个可以帮你简化移动app开发流程的工具

    如果想进入移动app开发这个领域,你总能从别的开发者或者网上或者书上找到各种各样的方法和工具,对于新手来说,还没有摸清门路就已经陷入迷茫了.这里推荐20个可以帮你简化app开发流程的工具.很多开发者都 ...

  7. Linux 更改时区

    原文:https://www.cnblogs.com/st-jun/p/7737188.html Linux修改时区的正确方法 CentOS和Ubuntu的时区文件是/etc/localtime,但是 ...

  8. ASP.NET MVC与ASP.NET WebForm

    ASP.NET MVC是微软公司的一款WEB开发框架,整合了“模型-视图-控制器”架构的高效与整洁,是敏捷开发最现代的思想与技术.它是传统ASP.NET WebForm的一个完善的替代品. 1.当今的 ...

  9. jquery replace方法去空格

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. 地图的平移、缩放的实现(android版)

    一.平移地图 移动地图的原理是利用手指在屏幕上拖动的距离,转换为在地图上距离,把地图坐标加上偏移的距离实现地图移动. 由于地图是绘制到Bitmap上的,所以地图移动和缩放的过程只要改变Bitmap的矩 ...