scala開發快速入門 | 第六篇 面向物件程式設計(下)
阿新 • • 發佈:2018-12-25
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只能是 Person03或Person03的子類*/
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泛型 以為Master是Professor的父類
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
/*這個是協變 Professor是Master的子類 那麼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
/*這個是逆變 Professor是Master的子類 那麼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) 編譯報錯
}
}