第十五章
注解让程序员可以在程序中的各项条目中添加信息。这些信息可以被编译器或外部工具处理。
要点
- 注解是那些可以插入到代码中以便有工具可以对它们进行处理的标签。工具可以在代码级别用作,也可以处理被编译器加入了注解信息的类文件。
- Java注解并不影响编译器如何将源码翻译成字节码,而在Scala中,注解可以影响编译过程。
- 可以为类、方法、字段、局部变量、参数、表达式、类型参数以及各种类型定义添加注解。
- 对于表达式和类型,注解跟在被注解的条目之后。
- 注解的形式有@Annotation、@Annotation(value)或@Annotation(name1 = vaule1, …)
- @valatile、@transient、@strictfp和@native分别生成等效的Java修饰符。
- 用@throws生成与Java兼容的throws规格说明。
- @tailrec注解让你校检某个递归函数使用了尾递归优化。
- assert函数利用了@elidable注解。可以选择从Scala程序中移除所有断言。
- 用@deprecated注解标记已经过时的特性。
第十七章
Scala中,可以用类型参数来实现类和函数,这样的类和函数可以用于多种类型。
要点
- 类、特质、方法和函数都可以有类型参数。
将类型参数放置在名称之后,以方括号括起来。如:
class Pair[T, S](val first: T, val second: S) //Scala会从构造参数推断出实际类型 val p = new Pair(42, "String") //也可以自己指定类型: val p2 = new Pair[Any, Any](42, "String")
函数和方法也可以带类型参数,如:
def getMiddle[T](a: Array[T]) = a(a.length / 2)
类型界定的语法为T<:UpperBound、T>:LowerBound、T<%ViewBound、T:ContextBound。
例如考虑如下Pair类型,它要求它的两个组件类型相同: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 } //仍然有问题,首先Int在这里就会报错,因为Int并不是Comparable[Int]的子类,和java.lang.Integer包装类型不同,Scala的Int类型并没有实现Comparable,不过RichInt实现了,同时还有一个从Int到RichInt的隐式转换,用视图界定来实现。<% 意味着 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的超类。 class Pair[T](val first: T, val second: T) { def replaceFirst[R >: T](newFirst: R) = new Pair[R](newFirst, second) } //上下文界定的形式为 T : M,其中M为另一个泛型类,它要求必须存在一个类型为M[T]的“隐式值”,例如 class Pair[T: Ordering](val first: T, val second: T) { def smaller(implicit ord: Ordering[T]) = if (ord.compare(first, second) < 0) first else second }//当声明一个使用隐式值的方法时,需要添加一个“隐式参数”,隐式值比隐式转换更加灵活(21章介绍)
要实例化一个泛型Array[T],需要使用Manifest[T]对象(在虚拟机中,泛型相关的类型信息是被抹掉的)
- 多重界定,类型变量可以同时有上界和下界,写作 T >: Lower <: Upper
- 不能同时有多个上界或多个下界,但是可以要求一个类型实现多个特质 T <: Comparable[T] with Serializable with Cloneable
- 也可以有多个视图界定和多个上下文界定
类型约束是另一个限定类型的方式,总共有三种关系。
T =:= U
T <:< U
T <%< U
可以用类型约束来约束一个方法,比如(implicit ev:T<:< UpperBound)型变
- 用+T(协变)来表示某个泛型类的子类型关系与参数T方向一致,或用-T(逆变)来表示方向相反。
- 协变适用于表示输出的类型参数,比如不可变集合中的元素。
- 逆变适用于表示输入的类型参数,比如函数参数。
- 如果一个对象同时消费和产出某值,则类型应该不变。