2013-04-25 52 views
1

我試圖創建一個監聽器的設計模式那樣:NullPointerException異常上一階監聽器模式

abstract class Listener(g: Engine) { 
    g.addListener(this) 
} 
class Listener1(g: Engine) extends Listener(g) 
class Listener2(g: Engine) extends Listener(g) 

class Engine { 
    val listener1 = new Listener1(this) 
    val listener2 = new Listener2(this) 

    var listeners: List[Listener] = Nil 
    def addListener(g: Listener) = { 
    listeners = g::listeners 
    } 
} 

但如果失敗了NullPointerException,因爲listeners最初等於null創建listener1listener2時。

我該如何解決這個問題?

編輯:我試過如下:

def addListener(g: Listener) = { 
    if(listeners == null) { 
     listeners = List(g) 
    } else { 
     listeners = g::listeners 
    } 
    } 

但問題是類初始化後,聽衆=無。 我需要一個更好的設計模式來實現我的目標。

SOLUTION:不使用懶惰VAL或可變集合:

var listeners: List[Listener] = _ 
def addListener(g: Listener) = { 
    if(listeners == null) 
    listeners = List(g) 
    else 
    listeners = g::listeners 
} 

使用_初始化,而不是「空」或「無」,使編譯器不listener1後覆蓋listenerslistener2已創建。

+0

實際上用'_'進行初始化與將偵聽器設置爲null – 2013-04-25 13:16:14

+0

不一樣,因爲如果用null替換_,則偵聽器在末尾將等於null。 – 2013-04-25 13:17:23

回答

2

隨着lazy valuemutable collection幫助:

class Engine { 
    val listener1 = new Listener1(this) 
    val listener2 = new Listener2(this) 

    lazy val listeners = collection.mutable.ListBuffer.empty[Listener] 
    def addListener(g: Listener) { 
    listeners += g 
    } 
} 

如果您急需不可變List地方的道路,只是把緩存到它在callplace .toList方法。

+0

謝謝,它的工作原理。但爲什麼?如果我理解正確,懶惰的val定義了一個新的類,在第一次調用之後計算內容,不是嗎?但就我而言,偵聽器可能甚至在addListener方法中都沒有定義,即使它是懶惰的。 – 2013-04-25 12:37:31

+0

不像普通的val,懶惰的val延遲初始化到第一次訪問的時刻(和[具有相當複雜的實現](http://stackoverflow.com/questions/3041253/whats-the-hidden-cost-of-scalas-lazy- val)) - 已定義,但尚未設置。無論懶惰與否,偵聽器變量都像addListener的角度看起來像一個類字段。 – 2013-04-25 12:46:18

+0

我接受你的解決方案,因爲我喜歡它,但我也加入了我的工作,沒有懶惰val或可變集合。 – 2013-04-25 13:14:33

相關問題