Spark基础-scala学习(七、类型参数)

类型参数是什么

  1. 类似于java泛型,泛型类
  2. 泛型函数
  3. 上边界Bounds
  4. 下边界
  5. View Bounds
  6. Context Bounds
  7. Manifest Context Bounds
  8. 协变和逆变
  9. Existential Type

泛型类

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Student[T](val localId:T){
 def getSchoolId(hukouId:T) = "S-"+hukouId+"-"+localId
}

// Exiting paste mode, now interpreting.

defined class Student

scala> val s = new Student[Int](11)
s: Student[Int] = [email protected]

scala> s.getSchoolId(234)
res1: String = S-234-11

泛型函数

  1. 泛型函数,与泛型类类似,可以给某个函数在声明时指定泛型类型,然后在函数体内,多个变量或者返回值之间,就可以使用泛型类型进行声明,从而对某个特殊的变量,或者多个变量,进行强制性的类型限制
  2. 与泛型类一样,你可以通过使用了泛型类型的变量传递值来让Scala自动推断泛型的实际类型,也可以在调用函数时,手动指定泛型类型
scala> :paste
// Entering paste mode (ctrl-D to finish)

def getCard[T](content:T)={
 if(content.isInstanceOf[Int]) "card: 001,"+content
 else if(content.isInstanceOf[String]) "card:this is your card, "+content
 else "card: "+content
}

// Exiting paste mode, now interpreting.

getCard: [T](content: T)String

scala> getCard[String]("leo")
res2: String = card:this is your card, leo

scala> getCard[Int](123)
res3: String = card: 001,123

上边界Bounds

  1. 在指定泛型类型的时候,有时,我们需要对泛型类型的范围进行界定,而不是可以是任意的类型。比如,我们可能要求某个泛型类型,他就必须是某个类的子类,这样在程序中就可以放心地调用泛型类型继承的父类的方法,程序才能正常的使用和运行。此时就可以使用上下边界Bounds的特性
  2. scala的上下边界特性允许泛型类型必须是某个类的子类,或者必须是某个类的父类
scala> :paste
// Entering paste mode (ctrl-D to finish)

class Person(val name:String){
 def sayHello = println("Hello,I‘m "+name)
 def makeFriends(p:Person){
  sayHello
  p.sayHello
 }
}
class Student(name:String) extends Person(name)
class Party[T <: Person](p1:T,p2:T){
 def play = p1.makeFriends(p2)
}

// Exiting paste mode, now interpreting.

defined class Person
defined class Student
defined class Party

scala> val p = new Person("Tom")
p: Person = [email protected]

scala> val p2 = new Person("leo")
p2: Person = [email protected]

scala> p.makeFriends(p2)
Hello,I‘m Tom
Hello,I‘m leo

scala> val s1 = new Student("Jarry")
s1: Student = [email protected]

scala> val s2 = new Student("Marry")
s2: Student = [email protected]

scala> val pa = new Party[Student](s1,s2)
pa: Party[Student] = [email protected]

scala> pa.play
Hello,I‘m Jarry
Hello,I‘m Marry

下边界Bounds

  1. 除了指定泛型类型的上边界,还可以指定下边界,即指定泛型类型必须是某个类的父类
scala> :paste
// Entering paste mode (ctrl-D to finish)

class Father(val name:String)
class Child(name:String) extends Father(name)

def getIDCard[R >: Child](person:R){
 if(person.getClass == classOf[Child]) println("please tell us your parents‘ names.")
  else if(person.getClass == classOf[Father]) println("sign your name for your child‘s id card.")
  else println("sorry,you are not allowed to get id card.")
}

// Exiting paste mode, now interpreting.

defined class Father
defined class Child
getIDCard: [R >: Child](person: R)Unit

scala> val f = new Father("fa")
f: Father = [email protected]

scala> val c = new Child("cd")
c: Child = [email protected]

scala> getIDCard[Father](f)
sign your name for your child‘s id card.

scala> getIDCard[Child](c)
please tell us your parents‘ names.

View Bounds

  1. 上下边界Bounds,虽然可以让一种泛型类型,支持有父子关系的多种类型。但是,在某个类与上下边界Bounds指定的父子类型范围内的类都没有任何关系,则默认是肯定不能接受的
  2. 然而,View Bounds作为一种上下边界Bounds的加强版,支持可以对类型进行隐式转换,将指定的类型进行隐式转换后,再判断是否在边界指定的类型范围内
  3. 案例:跟小狗交朋友
scala> :paste
// Entering paste mode (ctrl-D to finish)

class Person(val name:String){
 def sayHello = println("Hello,I‘m "+name)
 def makeFriends(p:Person){
  sayHello
  p.sayHello
 }
}
class Student(name:String) extends Person(name)
class Dog(val name:String){def sayHello = println("Wang,Wang,I‘m "+name)}

implicit def dog2person(dog: Object):Person = if(dog.isInstanceOf[Dog]){val _dog = dog.asInstanceOf[Dog];new Person(_dog.name)} else Nil
class Party[T <% Person](p1:T,p2:T)

// Exiting paste mode, now interpreting.

<pastie>:23: warning: implicit conversion method dog2person should be enabled
by making the implicit value scala.language.implicitConversions visible.
This can be achieved by adding the import clause ‘import scala.language.implicitConversions‘
or by setting the compiler option -language:implicitConversions.
See the Scaladoc for value scala.language.implicitConversions for a discussion
why the feature should be explicitly enabled.
implicit def dog2person(dog: Object):Person = if(dog.isInstanceOf[Dog]){val _dog = dog.asInstanceOf[Dog];new Person(_dog.name)} else Nil
             ^
defined class Person
defined class Student
defined class Dog
dog2person: (dog: Object)Person
defined class Party

scala> val leo = new Student("leo")
leo: Student = [email protected]

scala> val doggy = new Dog("doggy")
doggy: Dog = [email protected]

scala> val party = new Party(leo,doggy)
party: Party[Object] = [email protected]

Context Bounds

  1. Context Bounds是一种特殊的Bounds,它会根据泛型类型的声明,比如“T:类型”要求必须存在一个类型为“类型[T]”的隐式值。其实个人认为,Context Bounds之所以叫做Context,是因为它基于的是一种全局的上下文,需要使用到上下文中的隐式值以及注入
  2. 案例:使用Scala内置的比较器比较大小
scala> :paste
// Entering paste mode (ctrl-D to finish)

class Calculator[T:Ordering](val number1:T,val number2:T){
  def max(implicit order:Ordering[T]) = if(order.compare(number1,number2)>0)number1 else number2
}

// Exiting paste mode, now interpreting.

defined class Calculator

scala> val ca = new Calculator[Int](12,23)
ca: Calculator[Int] = [email protected]

scala> ca.max
res8: Int = 23

Manifest Context Bounds

  1. 在scala中,如果要实例化一个泛型数组,就必须使用Manifest Context Bounds,也就是说,如果数组元素类型为T的话,需要为类或者函数定义[T:Manifest]泛型类型,这样才能实例化Array[T]这种泛型数组
  2. 案例:打包饭菜(一种食品打成一包)
scala> :paste
// Entering paste mode (ctrl-D to finish)

class Meat(val name:String)
class Vegetable(val name:String)

def packageFood[T:Manifest](food: T*) = {
 val foodPackage = new Array[T](food.length)
 for(i <- 0 until food.length) foodPackage(i) = food(i)
 foodPackage
}

// Exiting paste mode, now interpreting.

defined class Meat
defined class Vegetable
packageFood: [T](food: T*)(implicit evidence$1: Manifest[T])Array[T]

scala> val gongbaojiding = new Meat("gongbaojiding")
gongbaojiding: Meat = [email protected]

scala> val shoushibaocai = new Meat("shoushibaocai")
shoushibaocai: Meat = [email protected]

scala> val meatPackage = packageFood(gongbaojiding,shoushibaocai)
meatPackage: Array[Meat] = Array([email protected], [email protected])

协变和逆变

  1. scala的协变和逆变完全解决了java中的泛型的一大缺憾
  2. 举例来说,java中,如果有professional是Master的子类,那么Card(Professionnal)是不是Card(Master)的子类呢?答案是:不是。
  3. 而scala中,只要灵活使用协变和逆变,就可以解决java泛型的问题
  4. 案例:进入会场
scala> :paste
// Entering paste mode (ctrl-D to finish)

class Master
class Professional extends Master

//大师以及大师级别以下的名片都可以进入会场
class Card[+T](val name:String)
def enterMeet(card:Card[Master]){
 println("Welcome to have this meeting")
}

// Exiting paste mode, now interpreting.

defined class Master
defined class Professional
defined class Card
enterMeet: (card: Card[Master])Unit

scala> val leo = new Card[Master]("leo")
leo: Card[Master] = [email protected]

scala> val jack = new Card[Professional]("jack")
jack: Card[Professional] = [email protected]

scala> enterMeet(leo)
Welcome to have this meeting

scala> enterMeet(jack)
Welcome to have this meeting

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Card[-T](val name:String)
def enterMeet(card:Card[Professional]){
 println("welcome to have this meeting!")
}

// Exiting paste mode, now interpreting.

defined class Card
enterMeet: (card: Card[Professional])Unit

scala> val leo = new Card[Master]("leo")
leo: Card[Master] = [email protected]

scala> val jack = new Card[Professional]("jack")
jack: Card[Professional] = [email protected]

scala> enterMeet(leo)
welcome to have this meeting!

scala> enterMeet(jack)
welcome to have this meeting!

Existential Type

  1. 在scala中,有一种特殊的类型参数,就是Existential Type存在性类型。
Array[T] forSome {type T}
//占位符
Array[_]

原文地址:https://www.cnblogs.com/sky-chen/p/10128927.html

时间: 2024-11-07 03:40:17

Spark基础-scala学习(七、类型参数)的相关文章

Spark基础-scala学习(三)

面向对象编程之Trait trait基础知识 将trait作为接口使用 在trait中定义具体方法 在trait中定义具体字段 在trait中定义抽象字段 trait高级知识 为实例对象混入trait trait调用链 在trait中覆盖抽象方法 混合使用trait的具体方法和抽象方法 trait的构造机制 trati字段的初始化 让trait继承类 将trait作为接口使用 trait作为接口,和java中的接口非常类似 在triat中可以定义抽象方法,就与抽象类中的抽象方法一样,只要不给出方

Spark基础-scala学习(一)

Scala解析器的使用 REPL:Read(取值)-> Evaluation(求值)-> Print(打印)->Loop(循环).scala解析器也被称为REPL,会快速编译scala代码为字节码,然后交给JVM执行 val result = 1 设置变量不可变 var result = 2 可变的变量 val name: String = null 声明变量类型 val name: Any = "leo" val name1,name2:String = null

Spark基础-scala学习(四)

函数式编程 将函数赋值给变量 匿名函数 高阶函数 高级函数的类型推断 scala的常用高阶函数 闭包 sam转换 currying函数 return 将函数赋值给变量 scala中的函数是一等公民,可以独立定义,独立存在,而且可以直接将函数作为值赋值给变量 scala> def sayHello(name:String){println("Hello, "+name)} sayHello: (name: String)Unit scala> sayHello("t

Spark基础-scala学习(五、集合)

集合 scala的集合体系结构 List LinkedList Set 集合的函数式编程 函数式编程综合案例:统计多个文本内的单词总数 scala的集合体系结构 scala中的集合体系主要包括:Iterable.Seq.Set.Map.其中Iterable是所有集合trait的根trait.这个结构与java的集合体系非常相似 scala中的集合是分成可变和不可变两类集合的,其中可变集合就是说,集合的元素可以动态修改,而不可变集合的元素在初始化之后,就无法修改了.分别对应scala.collec

Spark之Scala学习

1. Scala集合学习: http://blog.csdn.net/lyrebing/article/details/20362227 2. scala实现kmeans算法 http://www.thinksaas.cn/group/topic/93852/ 3. Spark之Scala学习网站 http://spark.apache.org/docs/latest/mllib-decision-tree.html 4. Spark wordcount开发并提交到集群运行: http://ww

scala学习笔记-类型参数(17)

类型参数是什么? 类型参数其实就类似于Java中的泛型.先说说Java中的泛型是什么,比如我们有List a = new ArrayList(),接着a.add(1),没问题,a.add("2"),然后我们a.get(1) == 2,对不对?肯定不对了,a.get(1)获取的其实是个String--"2",String--"2"怎么可能与一个Integer类型的2相等呢? 所以Java中提出了泛型的概念,其实也就是类型参数的概念,此时可以用泛型创

scala学习笔记-类型参数中协变(+)、逆变(-)、类型上界(&lt;:)和类型下界(&gt;:)的使用

转载自  fineqtbull   http://fineqtbull.iteye.com/blog/477994 有位je上的同学来短信向我问起了Scala类型参数中协变.逆变.类型上界和类型下界的使用方法和原理,自己虽然也刚学不久,在主要调查了<Programing in Scala>的19章后,试着在下面做一个总结.如有错误之处还请各位指正. 先说说协变和逆变(实际上还有非变).协变和逆变主要是用来解决参数化类型的泛化问题.由于参数化类型的参数(参数类型)是可变的,当两个参数化类型的参数

Scala学习(七)练习

控制结构和函数 1. 编写示例程序,展示为什么 package com.horstmann.impatient 不同于 package com package horstmann package impatient 描述: 区别是后者的上层包也可见,而串写的只有当前包范围可见 程序代码: b.scala package com{   package horstmann{     object A{       def hi=println("I am A")     }     pac

Scala学习(七)---包和引入

包和引入 摘要: 在本篇中,你将会了解到Scala中的包和引入语句是如何工作的.相比Java不论是包还是引入都更加符合常规,也更灵活一些.本篇的要点包括: 1. 包也可以像内部类那样嵌套 2. 包路径不是绝对路径 3. 包声明链x.y.z并不自动将中间包x和x.y变成可见 4. 位于文件顶部不带花括号的包声明在整个文件范围内有效 5. 包对象可以持有函数和变量 6. 引入语句可以引入包.类和对象 7. 引入语句可以出现在任何位置 8. 引入语句可以重命名和隐藏特定成员 9. java.lang.