def getType(a:Any) //a是Any类型。
def getType[T](a:T) //a是泛型,getType是泛型函数。
当类型被指定的时候构成具体的类、函数等。
val getInt = getType[Int] _ 支持类型推断
val p1=new Pair(25,25.0) //生成Pair[Int,Double]类
val p2=new Pair(25.0,25)
2类型系统(了解)
2.1类型界定:
上界: A <: T
下界: A >: T 很少使用
上下界定: A >:T1 <: T2
视图界定: A <% T 隐式转化T
上下文界定: T:M 要求必须存在一个类型为M[T]的"隐式值"
2.1.1上下界
有时,需要对类型变量进行限制。考虑这样一个Pair类型,它要求它的两个组件类型相同,就像这样:
class Pair[T](val first:T,val second:T)
现在你想要添加一个方法,产出较小的那个值:
class Pair[T](val first:T,val second:T){
def smaller=if (first.compareTo(second) <0) first else second //错误
}
这是错的----我们并不知道first是否有compareTo方法。要解决这个问题,我们可以添加一个上界T<:Comparable[T]。
class Pair[T<:Comparable[T]](val first:T,val second:T){
def smaller=if (first.compareTo(second) <0) first else second
}
这意味着T必须是Comparable[T]的子类型。
这样一来,我们可以实例化Pair[java.lang.String],但不能实例化Pair[java.io.File],因为String是Comparable[String]的子类型,而File并没有实现Comparable[File]。
例如:
val p=new Pair("Fred","Books")
println(p.smaller)
2.1.2.视图界定
val p=new Pair(4,2)
编译器会抱怨说Int不是Comparable[Int]的子类型。和java.lang.Integer包装类型不同,Scala的Int类型并没有实现Comparable。不过,RichInt实现了Comparable[Int],同时还有一个从Int到RichInt的隐式转换。
解决办法就是使用"视图界定",就像下边一样:
class Pair[T <% Comparable[T]]
<%关系意味着T可以被隐式转化成Comparable[T]
class Pair[T <% Comparable[T]](val first:T,val second:T){def smaller=if (first.compareTo(second) <0) first else second }
2.1.3.多重界定
T >: lower <:upper //同时有上下界,但不能同时有多个上界或下界
T <: Ordered[T] with Cloneable //能要求同时混入多个特质
T <% Ordered[T] <% String //能同时多个视图限定
T : Ordering : Manifest //能同时多个上下文界定
2.2.类型约束
A =:= T A是否等于T
A <:< T A是否为T的子类
A <%< T A是否可以隐式转化成T
注意:使用类型约束需要使用implicit关键字
比如: class Pair[T](val name:T)(implicit ev:T<:<Comparable[T])
2.3.型变
在声明Scala的泛型类型时,“+”表示协变,而“-”表示逆变。
class List[-T]
List[String] List[Object]
协变:C[+T]:如果A是B的子类,那么C[A]是C[B]的子类。也就是被参数化类型的泛化方向与参数类型的方向是一致的,所以称为协变。
逆变:C[-T]:如果A是B的子类,那么C[B]是C[A]的子类。也就是被参数化类型的泛化方向与参数类型的方向是相反的,所以称为逆变。
不变:C[T]:无论A和B是什么关系,C[A]和C[B]没有从属关系。
例如:
class ScalaObject;
class Father extends ScalaObject;
class Son extends Father;
class Test1[T]
class Test2[+T]
class Test3[-T]
object Test extends App{
def test1(a:Test1[Father])={}
def test2(a:Test2[Father])={}
def test3(a:Test3[Father])={}
test1(new Test1[Father]);
//test1(new Test1[ScalaObject]);
//test1(new Test1[Son]);
test2(new Test2[Father]);
//test2(new Test2[ScalaObject]);
test2(new Test2[Son]);
test3(new Test3[Father]);
test3(new Test3[ScalaObject]);
//test3(new Test3[Son]);
}
Scala隐式转换(理解)
1隐式转换(掌握)
所谓隐式转换函数指的是以implicit关键字声明的带有单个参数的函数。这样的函数将被自动应用,将值从一种类型转化为另一种类型。
例如:将整数n转化为分数n/1
implicit def int2Fraction(n:Int)=new Fraction(n,1);
调用:
val result=3*Fraction(4,5)//将调用int2Fraction(3)
隐式转化函数将整数3转化成一个Fraction对象。这个对象接着乘以Fraction(4,5)
2利用隐式转化丰富现有类库的功能(掌握)
例如:往String类中添加自定义方法
解决办法:定义一个隐式转化的类
1.直接定义隐式转化类
implicit class MyString(val str:String){
def increment=str.map(x=>(x+1).toChar)
}
val str="hello";
str.increment//ifmmp
2.对象中的隐式转换类
package com.briup.base;
object StringUtils{
implicit class StringImprovements(val s:String){
def increment=s.map(x=>(x+1).toChar)
def decrement=s.map(x=>(x-1).toChar)
def hideAll=s.replaceAll(".","*")
}
}
import com.briup.base.StringUtils._
object Main extends App{
println("HAL".increment);
}
3.隐式转化类放在包对象中
package com.briup.base;
package object utils{
implicit class StringImprovements(val s:String){
def increment=s.map(x=>(x+1).toChar)
}
}
import com.briup.base.utils._
object Main extends App{
println("HAL".increment);
}
4.使用scala 2.10之前的版本
定义一个经过丰富的类型,提供你想要的功能
class MyString(val str:String){
def increment=str.map(x=>(x+1).toChar)
}
在提供一个隐式转换函数将原类的类型转化到这个新的类型
implicit def string2String(s:String)=new MyString(s);
val str="hello";
str.increment