天天看點

Scala第四章學習筆記(面向對象程式設計)

延遲構造

DelayedInit特質是為編譯器提供的标記性的特質。整個構造器被包裝成一個函數并傳遞給delayedInit方法。

trait DelayedInit {
    def deayedInit(x : Unit) : Unit
}      

這個方法接受一個函數對象,函數對象裡包含了全部的一般的構造器邏輯

trait App extends DelayedInit{
    var x : Option[Function0[Unit]] = None
    override def delayedInit(cons : => Unit){
        x = Some(() => cons)
    }
    def main(args : Array[String]) : Unit = 
        x.foreach(_())
 }      

如上代碼,它定義了一個Option x用來容納構造器行為。覆寫了delayedInited方法。在X變量裡存放構造器邏輯,main方法去執行存放在x變量裡的構造器邏輯。

Scala第四章學習筆記(面向對象程式設計)

DelayedInit特質可以用于延遲整個對象的構造過程,直到所有屬性都被注入完成。

多重繼承

為特質的抽象方法提供空實作

首先建立一個SimulationEntity類,隻有一個handleMesaage方法,用于接收一個消息對象和一個上下文對象

trait SimulationEntity{
    def handleMessage(msg : SimulationMessage,ctx : SimulationContext) : Unit
}      

模拟系統設計為讓每個節點通過在上下文傳遞的消息。當一個實體收到消息時,它更新自身目前狀态并發送對應于該狀态的消息。上下文也可以用來在後面的模拟中(對各實體的行為)進行排程。

下來定義一個簡單的NetworkEntity特質和對應的行為(behavior)

trait NetworkEntity{
    def getMacAddress(ip : String) : String
    def hasIpAddress(addr : String) : Boolean
    
    def handleMessage(msg : SimulationMessage,ctx : Simulation) : Unit = msg match{
    case PingRequest(ip,sender) if hasIpAddress(ip) => 
        ctx respond(sender,PingResponse(getMacAddress(ip)))
    case _=>
        super.handleMessage(msg)
    }
}      

嘗試空實作的特質

trait MixableParent extends SimulationEntity{
    override def handleMessage(msg : SimulationMessage, ctx : SimulationContext) : Unit = {}
}

trait NetWorkENntity exntends MixableParent{
    def getMacAddress(ip : String) : String 
    def hasIpAddress(addr : String ) : Boolean
    
    override SimulationContext) : Unit = msg match{
        case PingRequest(ip , sender) if hasIpAddress(ip) => ctx respond(sender, PingResponse(getMacAddress(ip), this))
        case _=>
            super.handleMessage(msg,ctx)
    }
}

class Router extends SimulationEntity{
    override def handleMessage(msg : SimulationMessage,
    case Test(x) => println("YAY!" + x)
    case _=>
    }
}      

和Simulation類互動

val rtr = new MixableParent with Router with DummyNetworkEntity

    rtr.handleMessage(Test(5),null)
    
    val ctx = new SimulationContext{
        override def respond(entity : SimulationEntity,msg : SimulationMessage ) : Unit = {
        println("Sending " + msg + " to " + entity)
    }
}

rtr.handleMessage(PingRequest("HAI",rtr),ctx)      

是以在通過特質建立可混入的層級結構時,需要確定有一個特質可以假定為父類的"混入點(you have a "mixin" point that traits can asuume as parent")

組合可以包含繼承

由于Java不支援多重繼承,是以當子類需要組合兩個類的行為時,隻能繼承其中一個,而不得不重新實作另一個。

那麼下述案例 基于繼承來組合Logger 和 DataAccess

trait logger{
    def log(category : String , msg : String ) : Unit = {
            println(msg)
    }
}

traqit DataAccess{
    def query[A](in : String) : A = {
        ...
    }
}

trait LoggedDataAccess extends DataqAccess with Logger{
    def query[A](in : String) : A = {
        log("QUERRY", in)
        super.query(in)
    }
}      

 好不習慣。。。學的太尼瑪痛苦了T T