Scala学习—类型参数

泛型类
使用泛型类,通常是需要对类中的某些成员,比如field和method中的参数或变量,进行统一的类型限制,这样可以保证程序更好的健壮性和稳定性。
如果不使用泛型进行统一的类型限制,那么在后期程序运行过程中,难免会出现问题,比如传入了不希望的类型,导致程序出问题。
在使用类的时候,如果创建类的对象,将类型参数替换为实际的类型,即可。或者直接给使用了泛型类型的field赋值时,scala会自动进行类型推断。
案例:新生报到,每个学生来自不同的地方,id可能是Int,可能是String
class Student[T](val localId: T) {
def getSchoolId(hukould:T) = "S-" + hukould + "-" + localId
}
val leo = new Student[Int](111)

泛型函数
//泛型函数,与泛型类类似,可以给某个函数在声明时指定泛型类型,然后在函数体内,多个变量或者返回值之间,就可以使用泛型类型进行声明,从而对某个特殊的变量,或者多个变量,进行强制性的类型限制
与泛型类一样,可以通过使用了泛型类型的变量传递值来让Scala自动推断泛型的实际类型,也可以在调用函数时,手动指定泛型类型。
案例:卡片售卖机,可以指定卡片的内容,内容可以是String类型或Int类型
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
}
getCard(String)("Hello World")

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

案例:在派对上交朋友
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)
}

下边界Bounds
除了制定泛型类型的上边界,还可以制定下边界,即指定泛型类型必须是某个类的父类
案例:领身份证
class Father(val name:String)
class Child(name:String) extends Father(name)

def getIDCard(R >: Chiled)(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 child's id card")
else println("sorry, you are allowed to get id card")
}

View Bounds
上下边界Bounds,虽然可以让一种泛型类型,支持有父子关系的多种类型。但是,在某个类与上下边界Bounds指定的父子类型范围内的类都没有任何关系,则默认是肯定不能接受的。
然而,View Bounds作为一种上下边界Bounds的加强版,支持可以对类型进行隐式转换,将指定的类型进行隐式转换后,再判断是否在边界指定的类型范围内
案例:跟小狗交朋友
class Person(val name:String) {
def sayHello = ("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(obj:Object): Person = if(obj.isInstanceOf[Dog]) {val dog = obj.asInstanceOf[Dog]; new Person(dog.name)} else Nil

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

Context Bounds
Context Bounds是一种特殊的Bounds,它会根据泛型类型的声明,比如:“T:类型”要求必须存在一个类型为“类型[T]”的隐式值。它基于的是一种全局的上下文,需要使用上下文中的隐式值以及注入。
案例:使用scala内置的比较器比较大小
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
}

Manifest Context Bounds
在scala中,如果要实例化一个泛型数组,就必须使用Manifest Context Bounds。也就是说,如果数组元素类型为T的话,需要为类或者函数定义[T:Manifest]泛型类型,这样才能实例化Array[T]这种泛型数组。
案例:打包饭菜(一种食品打成一包)
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
}

协变和逆变

案例:进入会场
class Master
class Professional extends Master

//大师以及大师级别一下的名片都可以进入会场
class Card[+T](val name:String)
def enterMeet(card:Card[Master]) {
println("welcome to have this metting!")
}
//只要专家级别的明白就可以进入会场,如果大师级别的过来了,当然可以
class Card[-T] (val name:String)
def enterMeet(card:Card[Professional]) {
println("welcome to have this metting!")
}

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值