Scala学习--类型参数(泛型)

Scala中的类型参数类似于Java中的泛型。在Java中,比如有List a = new ArrayList(),接着a.add(1),a.add(“2”),然后a.get(1) == 2就不对了,因为a.get(1)获取的是一个字符串String–“2”.

所以Java提出了泛型的概念,用泛型创建List,List a = new ArrayList[Integer](),这样创建之后,a.add(1)没问题,a.add(“2”)就不行了。因为泛型限制只能往集合中添加Integer类型。

泛型类

//就是在类的声明中,定义一些泛型类型,然后在类内部,比如field或者method,就可以使用这些泛型类型。
//使用泛型类,通常是需要对类中的某些成员,比如某些field和method中的参数或变量,进行统一 的类型限制,这样可以保证程序更好的健壮性和稳定性。
//在使用类的时候,比如创建类的对象,将类型参数替换为实际的类型,即可。
//Scala自动推断泛型类型特性:直接给使用了泛型类型的field赋值时,Scala会自动进行类型推断。

案例:新生报到,每个学生来自不同的地方,id可能是Int,可能是String

class Student[T](val localId:T){
	def getSchoolId(hukouId:T) = "S-" + hukouId + "-" + localId
}
调用:
val xiaoming = new Student[Int](111)
xiaoming.getSchoolId(222)

泛型函数

与泛型类相同
案例:卡片售卖机,可以指定卡片的内容,内容可以是String类型或Int类型

def getCard[T](content:T) = {
	if(content.isInstanceOf[Int]) println("card:this is normal card " + content)
	else if(content.isInstanceOf[String]) println("card:this is string card " + content)
	else println("card: " + content)
}
调用:
getCard[Int](111)
getCard[Int]("111")        //错误

上边界Bounds

//在指定泛型类型的时候,有时,我们需要对泛型类型的范围进行界定,而不是可以是任意类型。比如,我们可能要求某个泛型类型,它必须是某个类的子类,这样在程序中就可以放心的调用泛型类型继承的父类的方法,程序才能正常的使用和运行。
//Scala的上下边界特性允许泛型类型必须是某个类的子类,或者必须是某个类的父类。

案例:交朋友

class Preson(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){     //限定传入的对象必须是Person类的对象或者Person类的子类的对象
	def play = p1.makeFriends(p2)
}

调用:
val xiaoming = new Student("xiaojming")
val laowang = new Student("laowang")

val party = new Party(xiaoming,laowang)
party.play

下边界Bounds

//指定下边界,即指定泛型类型必须是某个类的父类

案例:领身份证

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

def getIdCard[T >: Child](p:T){
	if(p.getClass == classOf[Child]) pringln("please tell us your parents's names")
	else if(p.getClass == classOf[Father]) println("please sign your name and tell us your child's lost id card")
	else println("sorry,you are not alloe to get this id card")
}
调用:
val xiaoming = new Father("xiaoming")
val laownag = new Child("laowang")

getIdCard(xiaoming)

View Bounds

View Bounds作为一种上下边界Bounds的加强版,支持可以对类型进行隐式转换,将指定的类型进行隐式转换后,再判断是否在边界指定的类型范围内。
案例:跟小狗交朋友

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)

Context Bounds

Context Bounds是一种特殊的Bounds,它会根据泛型类型的声明,比如”T:类型“要求必须存在一个类型为"类型[T]"的隐式值。其实Context Bounds之所以叫Context,是因为它基于的是一种全局的上下文,需要使用到上下文中的隐式值以及注入。

案例:使用Scala内置的比较器比较大小。

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

Manifest Context Bounds

在Scala中,如果要实例化一个泛型数组,就必须使用Manifest Context Bounds。也就是说,如果数组元素类型为T的话,需要为类或者函数定义[T:Manifest]泛型类型,这样才能实例化Array[T]这种泛型数组。

案例:打包饭菜(一种食品打成一包)

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

def pakeageFood(T:Manifest)(food:T*) = {      //定义泛型类型,变长参数
	val foodPackage = new Array[T](food.length)
	for(i <- 0 until food.length) foodPackage(i) = food(i)
	foodPackage
}

调用:
val gongbaojiding = new Meat("gongbaojiding")
val yuxiangrousi = new Meat("yuxiangrousi")
val shousibaocai = new Meat("shousibaocai")
val meatPackage = packageFood(gongbaojiding,yuxiangrousi,shousibaocai)

协变和逆变

Scala的协变和逆变是非常有特色的,完全解决了Java中的泛型的一大缺陷
举例来说,Java中,如果有Professional是Master的子类,那么Card[Perfessionnal]并不是Card[Master]的子类,这就会对开发程序造成很多的麻烦

案例:进入会场

class Master
class Professionnal extends Master

//大师以及大师级别以下的名片都可以进入会场(向下包容)
class Card[+T](val name:String)         //如果Master是Proffessionnal的父类,那么Card[Master]也是Card[Professionnal]的父类
def enterMeet(card:Card[Master]){
	println("Welcome to have this meeting")
}

//只要专家级别的名片就可以进入会场,如果大师级别的过来了,当然可以了(向上包容)
class Crad[-T](val name:String)   //如果Master是Professionnal的子类,那么Card[Professionnal]也是Card[Master]的子类
def enterMeet(card:Card[Professionnal]){
	println("Welcome to have this meeting")
}

Existential Type

Array[T] forSome{type T}
Array[_]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值