为什么使用泛型
不适用泛型,可能有些变量在编译的过程中不能发现,在执行的时候才能发现。
类型的约束,使用泛型之后,只有使用规则的数据才能使用。
泛型代码示例
object GenericApp {
def main(args: Array[String]): Unit = {
new WeChatMsg("wechat message")
new DigitMsg(200)
val man1 = new Man[String, Int, HobbyEnum]("zhangsan", 70, HobbyEnum.BASEBALL)
val man2 = new Man[String, Int, HobbyEnum]("lisi", 80, HobbyEnum.BASEBALL)
val man3 = new Man[String, Int, HobbyEnum]("wangwu", 90, HobbyEnum.BASEBALL)
println(man1)
println(man2)
println(man3)
}
}
//最顶层是个任意类型
abstract class Msg[T](content: T)
//WebChatMsg 和 DigitMst对类型进行了约束
class WeChatMsg[String](content: String) extends Msg(content) {
println(content)
}
class DigitMsg[Int](content: Int) extends Msg(content) {
println(content)
}
class Man[A, B, C](val name: A, val height: B, val hobby: C) {
override def toString: String = s"$name\t$height\t$hobby"
}
//Scala枚举的使用
object HobbyEnum extends Enumeration {
type HobbyEnum = Value
val SWIM, JUMP, BASEBALL = Value
}
通过Java泛型,对比Scala泛型
Java 泛型
<? extends Test> ?可以是Test的子类型(T extends Test),这里的 ? 被称为上届(upper bounds)
<? super Test> ?可以是Test的父类型,这里的 ? 被称为下届(lower bounds)
T extends Test,其中 T 为上届( upper bounds),即T的类型最多到Test
下届(lower bounds) <T super Test> T可以是test的父类型
举例说明Scala的泛型和Java泛型的关系
需求:在scala中实现一个比较两个数大小的函数
如果直接按照需求的语义来写,我们要把scala中的所有数据类型,按照如下的方式写一遍(例子中一Int和Long举例)
object UpperLowerBoundsApp {
def main(args: Array[String]): Unit = {
val maxInt = new MaxInt(10, 13)
println(maxInt.compare)
val maxLong = new MaxLong(10, 13)
println(maxLong.compare)
}
}
class MaxInt(x: Int, y: Int) {
def compare: Int = if (x > y) x else y
}
class MaxLong(x: Long, y: Long) {
def compare: Long = if (x > y) x else y
}
在scala中,可以通过泛型的方式来实现,但是在使用的过程中,需要注意一个点:
Scala中的所有值类的基类是AnyVal,即所有值类都是使用AnyVal接口来实现的,它并没有实现Comparable接口。
但是java中的数值是通过Comparable接口来实现的,所以我们在scala中调用泛型的时候,需要将数值类型定义为java中的数值类型。
object UpperLowerBoundsApp { def main(args: Array[String]): Unit = { /** * 我们如果直接使用 <: 来定义泛型来实现底层接口,在使用的时候会有如下问题 * val maxValue = new MaxValue[Int](10,13) * * Error type arguments [Int] do not conform to class MaxValue's type parameter bounds [T <: Comparable[T]] * val maxValue = new MaxValue[Int](10,13) * * 报错原因: * scala中Int的源码:final abstract class Int private extends AnyVal * 因此 scala并没有实现Comparable接口与 * * 但是 java 里的Integer public final class Integer extends Number implements Comparable<Integer> * java里的Integer是按照comparable来实现的 */ val maxValue1 = new MaxValue[Integer](10,13) val maxValue2 = new MaxValue(Integer.valueOf(10),Integer.valueOf(13)) println(maxValue1.compare) println(maxValue2.compare) /** * <: 定义的泛型,因为scala的数据类型没有实现comparable接口,不得不掉调用java底层的数据类型来实现 * 但是,在scala中,可以使用 <% 或者 >% 定义泛型,来直接在泛型中使用 * 这样能够使用scala 中的数据类型的原因是,在scala中,通过隐式转换的方式,是的 <% 既能实现comparable接口,有能兼容scala中的数据类型 */ val maxValue3 = new MaxValue2(10,13) println(maxValue3.compare) } } /** * 上届 * <: T是Comparable 这个类的子类型,即T必须是Comparable的子类(或本身,自己也可以认为是自己的子类) * * @tparam T */ class MaxValue[T <: Comparable[T]](x:T,y:T){ def compare:T = if (x.compareTo(y)>0) x else y } //视图界定:底层隐式转换了 class MaxValue2[T <% Comparable[T]](x:T,y:T){ def compare:T = if (x.compareTo(y)>0) x else y }