下面是相似於java的泛型,有三個類Shape(形狀)、Rectangle(長方形)、Square(正方形)。Shape是Rectangle的父類,Rectangle是Square的父類。因此咱們定義變量的時候,能夠聲明他爲Shape類型,在new的時候給具體的類型。
Draw1這裏有個泛型T,咱們能夠看到定義變量的時候,這裏的類型是不能有父子類關係的。java
object GenericDemo { def main(args: Array[String]): Unit = { val shape1: Shape = new Shape() var shape2: Shape = new Rectangle() var shape3: Shape = new Square() val draw1: Draw1[Shape] = new Draw1[Shape]() // val draw2: Draw1[Shape] = new Draw1[Rectangle]() // error // val draw3: Draw1[Shape] = new Draw1[Square]() // error } } class Shape { } class Rectangle extends Shape { } class Square extends Rectangle { } class Draw1[T]() { }
上面不能編譯是由於Draw1[Shape]和new Draw1[Rectangle]並無父子關係,Scala經過協變能夠讓他們有父子關係:
在泛型T前面加一個+
ide
class Draw2[+T]() { }
而後在main函數中就能夠調用了:函數
val draw2: Draw2[Shape] = new Draw2[Rectangle]() val draw3: Draw2[Shape] = new Draw2[Square]()
scala中還有逆變,就是顛倒Draw3[T]的父子關係:
在泛型T前面加一個-
scala
class Draw3[-T]() { }
而後在main函數中就能夠調用了:code
val draw4: Draw3[Rectangle] = new Draw3[Shape]() val draw5: Draw3[Square] = new Draw3[Shape]()
上界下界就是定義泛型的邊界。
好比Draw2經過<:
Shape2來定義泛型的上界,那Draw2的參數就是Shape2類以及子類。printInfo方法是Shape2的方法,因此printInfo中能夠直接調用。t.printInfo()方法,
Draw3經過>:
Rectangle2來定義泛型的下界,那Draw3的參數就是Rectangle2類以及父類,此時他只有Any的方法。get
object GenericDemo2 { def main(args: Array[String]): Unit = { val draw1: Draw2[Shape2] = new Draw2(new Shape2()) val draw2: Draw2[Shape2] = new Draw2(new Rectangle2()) val draw3: Draw2[Shape2] = new Draw2(new Square2()) draw1.printInfo() // 形狀 draw2.printInfo() // 長方形 draw3.printInfo() // 正方形 println("-------------") val draw4: Draw3[Shape2] = new Draw3(new Shape2()) val draw5: Draw3[Rectangle2] = new Draw3(new Rectangle2()) //val draw6: Draw3[Square2] = new Draw3(new Square2()) // error draw4.printInfo() // class com.scala.learn12.Shape2 draw5.printInfo() // class com.scala.learn12.Rectangle2 // draw3.printInfo() } } class Shape2 { def printInfo(): Unit = { println("形狀") } } class Rectangle2 extends Shape2 { @Override override def printInfo(): Unit = { println("長方形") } } class Square2 extends Rectangle2 { @Override override def printInfo(): Unit = { println("正方形") } } class Draw2[T <: Shape2](t: T) { def printInfo(): Unit = { t.printInfo() } } class Draw3[T >: Rectangle2](t: T) { def printInfo(): Unit = { println(t.getClass()) } }