(一)泛型
1.泛型类:定义类的时候,可以带有一个泛型的参数
For Example:
object GenericClass {
def main(args: Array[String]): Unit = {
//定义一个Int 类型
var v1 = new GenericClass[Int]
v1.set(1)
println(v1.get())
var v2 = new GenericClass[String]
v2.set("Hello Scala")
println(v2.get())
}
}
class GenericClassInt{
//定义一个整数的变量
private var content:Int = 10
//定义get和set
def set(value:Int) = {content = value}
def get():Int = {content}
}
class GenericClassString{
//定义一个整数的变量
private var content:String = ""
//定义get和set
def set(value:String) = {content = value}
def get():String = {content}
}
class GenericClass[T]{
//定义一个整数的变量
private var content:T = _
//定义get和set
def set(value:T) = {content = value}
def get():T = {content}
}
2.泛型函数:定义函数的时候,接收一个泛型参数
举例:
(1)定义函数:创建一个Int类型的数组
def mkIntArray(elem:Int*)= Array[Int](elem:_*)
mkIntArray(1,2,3)
(2)定义函数:创建一个String类型的数组
def mkStringArray(elem:String*)= Array[String ](elem:_*)
mkStringArray("Tomn","MArry")
(3)定义一个泛型函数
def mkTArray[T:ClassTag](elem:T*)= Array[T](elem:_*)
mkTArray("Hello Tag")
3.上界和下界upper bound lower bound
作用:是规定泛型的取值范围
4.视图界定:View bound:扩展了上界和下界
除了可以接收上界和下界规定的类型外,还可以接收能够通过隐式转换过去的类型用%表示
def addTwoString [T<%String](x:T,y:T)= {print(x+"***"+y)}
(1)可以接收String和String的子类
(2)可以接收能够转换成String的其他数据
调用 addTwoString(1,2)
error :No implicit view available from Int => String
一定定义转换的规则(通过隐式函数来实现):多了一个关键字implicit
implicit def int2String(n:Int):String = {n.toString}
调用:
addTwoString(1,2)
执行过程:(1)首先调用int2String,把int 转成String
(2)调用addString,拼加字符串
5.协变和逆变
概念:
(1)协变:表示在类型参数的前面加上 +
(2)逆变:表示在类型参数的前面加上 -
总结:Scala的协变:泛型变量的值可以是本身类型或者其子类的类型
Scala的逆变:泛型变量的值可以是本身类型或者其父类的类型
//Scala的协变:泛型变量的值可以是本身类型或者其子类的类型
object DemoClass {
def main(args: Array[String]): Unit = {
//定义一个鸟吃东西的对象
var c1:EatSomthing[Bird] = new EatSomthing[Bird](new Bird)
// var c2 :EatSomthing[Animal] = new EatSomthing[Animal](new Animal)
//问题:能否把c1付给c2
//原因:尽管Bird 是Animal的子类,但是EatSomeThing不是EatSomething[Animal]的子类
var c2:EatSomthing[Animal] = c1
}
}
class Animal
class Bird extends Animal
class Sparrow extends Bird
class EatSomthing[+T](t:T)
//Scala的逆变:泛型变量的值可以是本身类型或者其父类的类型
object DemoClass2 {
def main(args: Array[String]): Unit = {
//定义一个鸟吃东西的对象
var c1 :EatSomthing2[Bird2] = new EatSomthing2[Bird2](new Bird2)
//定义一个麻雀吃东西的对象
var c2 :EatSomthing2[Sparrow2] = c1
}
}
class Animal2
class Bird2 extends Animal2
class Sparrow2 extends Bird2
class EatSomthing2[-T](t:T)
(二)隐式转换
/**
* 定义一个隐式转换
*
* */
object ImplicitConversion {
//定义一个隐式转换函数,把Fruit纂成Monkey
implicit def fruit2Monkey(f:Fruit):Monkey = {new Monkey(f)}
def main(args: Array[String]): Unit = {
//定义一个水果对象
var f:Fruit = new Fruit("Banana")
//问题是:能否调用下面函数
//如果可以把水果转成monkey就可以调用
f.say()
}
}
//定义一个隐式转换函数
class Fruit(name:String){
//得到水果的名字
def getFruitName():String = name
}
//猴子
class Monkey(f:Fruit){
def say() = {println("Monkey Like "+f.getFruitName())}
}
隐式参数
概念:使用implicit 申明函数的参数叫隐式函数,我们也可以使用隐式参数实现隐式的转换
隐式类
目的是:增强类的扩展性
object ImplicitClassDemo {
//定义一个隐式类,来增加1这个对象的功能
implicit class Calc(x:Int){
def add(y:Int):Int = x+y
}
def main(args: Array[String]): Unit = {
//执行两个函数的求和
println("两个函数的和是:"+1.add(2))//实际上调用Calc.add方法
}
}
隐式类的执行过程:
1.当1.add(2),Scala的编译器不会立即报错,在当前域中查找,有没有implict修饰的,同时可以将Int作为参数的构造器。并且具有add方法的类。通过查找,找到了Calc
2.利用隐式类Calc来执行add方法