1. 泛型
  2. 类型边界
  3. 视图界定
  4. 逆变和协变
  5. 上下文界定
  6. 源代码

1.泛型

泛型用于指定方法或类可以接受任意类型参数,参数在实际使用时才被确定,泛型可以有效地增强程序的适用性,

使用泛型可以使得类或方法具有更强的通用性。

在Scala中用方括号来定义类型参数,即用[]表示,

如 class Pair[T, S](val first, val)

以上将定义一个带有两个类型参数T和S的类,带有类型参数的类是泛型的。如果把类型参数替换成实际的类型将得到普通的类。

*简单理解就是类型或者方法后面加个中括号就表示是泛型了,它可以放入任何类型,在实际实例化的时候指定具体的类型。*

2.类型边界

上边界:表达了泛型的类型必须是某种类型或者某种类的子类,语法为`<:`,例如T <: AnyVal表示泛型T的类型的最顶层类是AnyVal。

下边界:表达了泛型的类型必须是某种类型或者某种类的父类,语法为`>:`,例如T >: S表示泛型T的类型必须是S的超类,下界的作用主要是保证类型安全。

3.视图界定

如果希望类型变量界定能跨越类继承层次结构时,可以使用视图界定来实现的,

其后面的原理是通过隐式转换来实现。视图界定利用<%符号来实现,例如后面的例子[T <% Person],

T是Person继承的或者是能变成Person。

4.逆变和协变

逆变和协变最容易理解的便是用List来理解。

协变定义形式如:trait List[+T] {} 。当类型S是类型A的子类型时,则List[S]也可以认为是List[A}的子类型,

即List[S]可以泛化为List[A]。

逆变定义形式如:trait List[-T] {}

当类型S是类型A的子类型,则Queue[A]反过来可以认为是Queue[S}的子类型。

5.上下文界定

上下文界定的类型参数形式为T:M的形式,其中M是一个泛型,这种形式要求存在一个M[T]类型的隐式值。

6.源代码

 package com.dtspark.scala.basics

 /**

   * Scala类型系统编程实战:

   * 1,Scala的类和方法、函数都可以是泛型,在Spark源码中可以到处看到类和方法的泛型,在实际实例化的时候指定具体

   * 的类型,例如Spark最核心、最基础、最重要的抽象数据结构RDD里面关于RDD的类的定义是泛型的,RDD的几乎所有方法

   * 的定义也都是泛型的,之所以这么做,是因为RDD会派生很多子类,通过子类适配了各种不同的数据源以及业务逻辑操作;

   * 2, 关于对类型边界的限定,分为上边界和下边界:

   * 上边界:表达了泛型的类型必须是某种类型或者某种类的子类,语法为<:,这里的一个新的现象是对类型进行限定;

   * 下边界:表达了泛型的类型必须是某种类型或者某种类的父类,语法为>:;

   * 3, View Bounds,可以进行某种神秘的转换,把你的类型可以在没有知觉的情况下转换成为目标类型,其实你可以认为 View Bounds是

   * 上边界和下边界的加强补充版本,例如在SparkContext这个Spark的核心类中有T <% Writable方式的代码,这个代码所表达的是

   * T必须是Writable类型的,但是T有没有直接继承自Writable接口,此时就需要通过“implicit”的方式来实现这个功能;

   * 4, T: ClassTag,例如Spark源码中的RDD class RDD[T: ClassTag] 这个其实也是一种类型转换系统,只是在编译的时候类型信息不够,

   * 需要借助于JVM的runtime来通过运行时信息获得完整的类型信息,这在Spark中是非常重要的,因为Spark的程序的编程和运行是区分了

   * Driver和Executor的,只有在运行的时候才知道完整的类型信息。

   * 5, 逆变和协变;-T和+T

   * 6, Conext Bounds,T: Ordering这种语法必须能够编程Ordering[T]这种方式;

   */

 class Engineer

 class Expert extends Engineer

 //class Meeting[-T]

 class Meeting[+T]

 class Animal[T](val species: T) {

   def getAnimal(specie: T): T = species

 }

 class Maximum[T: Ordering](val x: T, val y: T) {

   def bigger(implicit ord: Ordering[T]) = {

     if (ord.compare(x, y) > 0) x else y

   }

 }

 object HelloScalaTypeSystem {

   def main(args: Array[String]): Unit = {

     println("=============上界===================")

     //创建Person,Worker两对象,从[T <: Person]来看要传入的参数是Person的本类或子类

     val p = new Person("Scala")

     val w = new Worker("Spark")

     //这里传入的参数满足要求,故能直接调用comunicate

     new Club1(p, w).comunicate

     println("=============视图界定===================")

     //Person,Worker是有继承结构的,而Dog狗与人是没有的,但是又想使用comunicate方法,怎么办?

     //答案就是让狗与人隐式的发生关系让狗可以变成人!

     val dog = new Dog("dahuang")

     //看见Club2[T <% Person]可知,传入的参数要是人(有继承结构)或者能变成人,

     //当传入狗时,会去找有没有狗变成人的方法

     implicit def dog2Person(dog: Dog) = new Person(dog.name)//找到了

     new Club2[Person](w, dog).comunicate//满足了要求,可以调用comunicate

     println("=============协变===================")

     val e = new Meeting[Engineer]

     participateMeeting(e)

     val expert = new Meeting[Expert]

     participateMeeting(expert)

     println("=============上下文界定===================")

     //因为[T: Ordering],所以传入的参数为Ordering[T],是可以比较的,所以调用

     //bigger(implicit ord: Ordering[T])方法,而方法参数是隐式参数就可以直接运行方法体内容,

     //由于存在Ordering[T],所以有compare方法,直接调用,返回x或y

     println(new Maximum("Scala", "Java").bigger)

   }

   /**

     * 传入参数类型为Meeting[Engineer],而class Meeting[+T],所以传入的参数可以是有继承结构的参数

     */

   def participateMeeting(meeting: Meeting[Engineer]) {

     println("Welcome")

   }

   class Person(val name: String) {

     def talk(person: Person) {

       println(this.name + " : " + person.name)

     }

   }

   class Worker(name: String) extends Person(name)

   class Dog(val name: String)

   class Club1[T <: Person](p1: T, p2: T){

     def comunicate = p1.talk(p2)

   }

   class Club2[T <% Person](p1: T, p2: T) {

     def comunicate = p1.talk(p2)

   }

 }

Scala之类型参数和对象的更多相关文章

  1. Scala 编程---类和对象

    类是对象的蓝图.一旦你定义了类,你就可以用关键字new从类的蓝图里创建对象.比方说,如果给出了类的定义: class ChecksumAccumulator { // class definition ...

  2. Scala:类,对象和特征(接口)

    http://blog.csdn.net/pipisorry/article/details/52902609 Scala类和对象 类是对象的抽象,而对象是类的具体实例.类是抽象的,不占用内存,而对象 ...

  3. scala学习-类与对象

    类 / 对象 [<快学Scala>笔记] 一.类 1.Scala中的类是公有可见性的,且多个类可以包含在同一个源文件中: class Counter{ private var value ...

  4. 快学Scala 第6章 对象 - 练习

    1. 编写一个Conversions对象,加入inchesToCentimeters.gallonsToLiters和milesToKilometers方法. object Conversions { ...

  5. Scala学习笔记——函数式对象

    用创建一个函数式对象(类Rational)的过程来说明 类Rational是一种表示有理数(Rational number)的类 package com.scala.first /** * Creat ...

  6. Scala学习之路 (六)Scala的类、对象、继承、特质

    一.类 1.类的定义 scala语言中没有static成员存在,但是scala允许以某种方式去使用static成员这个就是伴生机制,所谓伴生,就是在语言层面上,把static成员和非static成员用 ...

  7. scala中json与对象的转换

    遇到的问题 因为要把spark从es读出来的json数据转换为对象,开始想用case class定义类型,通过fastjson做转换.如下 case class Book (author: Strin ...

  8. scala actor编程之对象传递

    scala 最吸引人的一点就是actor并发编程了.但是纵观scala官方文档,baidu文档,IBM文档都写的通过字符串传呀传,如果用作actor编程说明当然没有问题.但是在正式开放中,光传字符串就 ...

  9. Scala学习笔记(6)对象

    1.单例对象.Scala没有静态方法或字段,可以使用object这个语法结构来达到同样的目的.对象定义了单个实例,包含了你想要的特性. object Accounts{ def newUniqueNu ...

随机推荐

  1. 用mciSendString做音乐播放器

    音乐操作类 public class clsMCI { public clsMCI() { // // TODO: 在此处添加构造函数逻辑 // } //定义API函数使用的字符串变量 [Marsha ...

  2. 大数据公益课堂成就你高薪之梦,30W,50W,100W...

    从之前的知道“大数据”这词,到2013年正式开始了解大数据领域,再到2014年深入研究大数据相关的领域,到现在逐渐影响周围的同学.朋友和家人.大数据技术将给我们带来的远不止我们想到的这些.曾经我身边的 ...

  3. select2使用

    一.简介 select2是Jquery用来代替选择框的一种组件.它让你可以定制下拉框,并且支持搜索.标记,远程数据源,无限滚动和其他更高级的功能.select2的下载地址为:https://selec ...

  4. golang中os/exec包用法

    exec包执行外部命令,它将os.StartProcess进行包装使得它更容易映射到stdin和stdout,并且利用pipe连接i/o. 1.func LookPath(file string) ( ...

  5. A class for global logging

    Some time we need to record the logging information in multiple module, however if we use the follow ...

  6. Swift 学习笔记 enum 枚举类型

    异端,异端啊,我感觉这是map吧? enum ATMStatus { case Success(Int) case Error(String) } func withdraw(amount: Int) ...

  7. PHP使用CURL实现对带有验证码的网站进行模拟登录的方法

    网上的很多模拟登录程序,大都是通过服务程序apache之类的运行,获取到验证码之后显示在网页上,然后填上再POST出去,这样虽然看起来很友 好,但是既然模拟登录,登录后所干的事情就不一定是短时间完成的 ...

  8. 动手学习TCP:TCP连接建立与终止

    TCP是一个面向连接的协议,任何一方在发送数据之前,都必须先在双方之间建立一条连接.所以,本文就主要看看TCP连接的建立和终止. 在开始介绍TCP连接之前,先来看看TCP数据包的首部,首部里面有很多重 ...

  9. [转]10个学习Android开发的网站推荐

    本文转自:http://blog.csdn.net/i_lovefish/article/details/43950893 1. Android Developers 作为一个Android开发者,官 ...

  10. selenium验证车贷计算器算法

    1.验证页面上的车贷计算器算的结果是否与需求中给的公式结果一致. 页面图片: 代码如下(简单实现,需要优化): package com.test; import java.math.BigDecima ...