1. 程式人生 > >scala開發快速入門 | 第六篇 面向物件程式設計(下)

scala開發快速入門 | 第六篇 面向物件程式設計(下)

trait簡介

在scala中並沒有提供java語言的interface關鍵字來定義介面,而是可以使用trait實現多重繼承,繼承的時候使用extends和with關鍵字。

/*定義三個trait*/
trait TraitDemo01 {
//  抽象方法定義
def say(content:String):Unit
}
trait TraitDemo02{
  //抽象方法定義
def sayHello(content:String):Unit
}

trait TraitDemo03{
  //抽象方法定義
def sayGoodBye(content:String):Unit
}

//trait 作為介面使用 那麼必須實現
trait的抽象方法 class TraitDemo04 extends TraitDemo01 with TraitDemo02 with TraitDemo03 { // 類實現trait的抽象方法 可以省略 override關鍵字 override def say(content: String): Unit = { println(content) } override def sayHello(content: String): Unit = { println(content) } override def sayGoodBye(content: String
): Unit = { println(content) } } object Application05{ def main(args: Array[String]): Unit = { val t1=new TraitDemo04 t1.say("say everything !") t1.sayHello("say hello!") t1.sayGoodBye("say GoodBye!") } }

trait中定義方法和欄位

1)trait中除了能夠定義抽象的欄位和抽象方法外,還能定義非抽象的欄位和方法    

2)和抽象類的唯一區別就是抽象類是單繼承,而trait是多實現。

例項物件中混入trait

例項物件混入 trait 那麼這個例項物件就擁有了trait的所有非私有方法。

/*例項物件中混入trait*/
trait TraitDemo05 {

  def say() = {
    println("say hello !")

  }
}
/*一個類繼承了父類或者trait,那麼這個類擁有該類或者trait的所有非私有的方法*/
class Baby(var name: String, var age: Int) {

}
object Application005 {
  def main(args: Array[String]): Unit = {

    val b1 = new Baby("xiaoming", 25)
    //為例項物件混入 trait 那麼這個例項物件就擁有了trait的所有非私有方法
val b2 = new Baby("xiaohua", 26) with TraitDemo05
    b2.say()
  }
}

繼承trait的構造構造機制

trait TraitDemos {
  println("這是TraitDemo03 的主程式碼塊!")

}
trait TraitDemos01 extends TraitDemos {
  println("這是TraitDemo04 的主程式碼塊!")

}
trait TraitDemos02 extends TraitDemos{
  println("這是TraitDemo05 的主程式碼塊!")

}
class Persons01{
  println("這個Person01的 主程式碼塊!")

}
class Students01 extends Persons01 with TraitDemos01 with TraitDemos02{
  println("這是 Students01的主程式碼塊 !")

}
object Students01{
  def main(args: Array[String]): Unit = {
    /**子類繼承了(類和trait)的構造機制如下
* 1、執行父類的構造程式碼塊
* 2、執行trait的構造程式碼塊,如果是多個trait那麼從左到右執行trait的程式碼塊
*    如果多個trait繼承了同一個trait那麼先執行父trait的構造程式碼,然後執行子trait的構造程式碼
*    trait的構造程式碼只執行一次
* 3、 最後執行自己的構造程式碼,即:子類的構造程式碼塊最後執行*/
val s1=new Students01
  }
}

泛型

在建立類和方法的時候可以指定類和方法的泛型。

泛型類

class FanXing[T1,T2,T3](var name:T1) {

  def say(): Unit ={
    println(name)

  }
  var age:T2=_
  var sex:T3=_

}
object FanXing{
  def main(args: Array[String]): Unit = {
    val s=new FanXing[String,Int,String]("ysj")
    s.say()
    s.age=18
s.sex="man"
println("name="+s.name+" "+"age="+s.age+" "+"sex"+s.sex)
  }
}

泛型函式

/*泛型方法*/
class FanXingFunction {
  def say[T1, T2, T3](name: T1, age: T2): T3 = {
    (name + "=" + age).asInstanceOf[T3]
  }
}
object FanXingFunction {
  def main(args: Array[String]): Unit = {
    val f = new FanXingFunction
    var result = f.say[String, Int, String]("xiaoming", 25)
    println(result)
  }
}

泛型類的上邊界

class Persons03
class Teacher03 extends Persons03
class Student03 extends Persons03

class Animal03
class Dog03 extends Animal03
class Cat03 extends Animal03

/*上邊界 <: 即泛型T只能是 Person03Person03的子類*/
class FanXingUpBound[T <: Persons03] {
  def say(content:T) ={
    println(content.getClass)
  }
}
object FanXingUpBound{
  def main(args: Array[String]): Unit = {
    val f1=new FanXingUpBound[Persons03]
    val t1=new Teacher03
    val s1=new Student03
    f1.say(t1)
    f1.say(s1)
    val f2=new FanXingUpBound[Teacher03]
    f2.say(t1)
    val f3=new FanXingUpBound[Student03]
    f3.say(s1)
    /*以下程式碼錯誤 因為animal不屬於Person03或其子類 不能作為FanXingUpBound的泛型*/
//    val animal=new FanXingUpBound[Animal03]
}
}

泛型類的下邊界

class Master

class Professor extends Master

class Teacher extends Professor

/*下邊界 >: T只能是Professor及其Professor的父類*/
class FanXingDownBound[T >: Professor] {
  def say(content: T): Unit = {
    println(content.getClass)
  }
}

object FanXingDownBound {
  def main(args: Array[String]): Unit = {
    //    Master 可以作為FanXingDownBound泛型 以為MasterProfessor的父類
val f1 = new FanXingDownBound[Master]
    //    Professor也可以作為FanXingDownBound泛型 因為Professor就是要求我們傳入的泛型
val f2 = new FanXingDownBound[Professor]
    //Teacher 不能作為FanXingDownBound泛型 因為Teacher 不是Professor以及Professor的父類
val f3 = new FanXingDownBound[Teacher]
  }
}

泛型協變

1)斜變在scala中是一種特色的功能,他完美的解決了java泛型的缺陷。

2)比如 Professor是Master的子類 那麼     Card[Professor] 是不是 card[Master]的子類呢? java是無法實現的但是scala的協變解決了此問題。

3)scala協變是泛型類上邊界的加強版

class Master05

class Professor05 extends Master05

class Teacher05

/*這個是協變 ProfessorMaster的子類 那麼Card[Professor] 也是Card[Master] 的子類*/
class Card[+T]

class FanXingXieBian {
  def say(card: Card[Master05]): Unit = {
    println("只要Master級別 以及下一級別的才能入場!")
  }

}
object FanXingXieBian{
  def main(args: Array[String]): Unit = {
    val cm=new Card[Master05]
    val cp=new Card[Professor05]
    val ct=new Card[Teacher05]

    val fx=new FanXingXieBian
    fx.say(cm)
    fx.say(cp)
//    fx.say(ct) 編譯報錯
}
}

泛型逆變

1)逆變在scala中也是一種特色的功能,他完美的解決了java泛型的缺陷。

2)比如 Professor是Master的子類 那麼 Card[Professor] 是不是 card[Master]的子類呢? java是無法實現的但是scala的逆變解決了此問題。

3)scala逆變是泛型類下邊界的加強版

class Master06
class Professor06 extends Master06
class Teacher06 extends Professor06
/*這個是逆變 ProfessorMaster的子類 那麼Card[Professor] 也是Card[Master] 的子類*/
class Card[-T]
class FanXingNiBian {

  def say(card: Card[Professor06]): Unit = {
    println("只要Professor06級別 以及上一級別的才能入場!")
  }

}
object FanXingNiBian{
  def main(args: Array[String]): Unit = {
    val cm=new Card[Master06]
    val cp=new Card[Professor06]
    val ct=new Card[Teacher06]

    val fx=new FanXingNiBian
    fx.say(cm)
    fx.say(cp)
//    fx.say(ct) 編譯報錯
}
}