2011-10-06 30 views
5

執行在重載的構造函數代碼假設我們有一類這樣的:之前調用這個()

import java.net.URL 
import xml._ 

class SearchData(xml: Node) { 
    def this(url: URL) = this (XML.load(url)) 
} 

,我們要執行之前調用this (XML.load(url))一些代碼 - 比如測試與try。人們預計,寫像這樣的工作:

class SearchData(xml: Node) { 
    def this(url: URL) { 
    try { 
     this (XML.load(url)) 
    } catch { 
     case _ => this(<results/>) 
    } 
    } 
} 

,但它不會,因爲Scala的要求,您對this()呼叫在重載的構造,在這種情況下try第一條語句成爲第一個語句。

那麼這個問題的解決方案是什麼?

回答

6
def this(url: Url) = this(try {XML.load(url)} catch {case _ => <results/>}) 

更一般地,自變量的評價具有構造函數調用之前發生的,所以你有(Scala中的一個模塊是一個表達式,而是寫一個程序,通常寫在同伴對象,如果它會太長)。你不能做的是讓這段代碼選擇你調用的其他構造函數。但是由於他們都必須前往主要路線,所以你不會損失太多。另外,你需要調用的另一個構造函數至少有一個參數。如果有幾個構造函數,主之一。通常不應該是不帶參數的一個(見Scala problem optional constructor

+0

所申報的問題的一個很好的解決方案,但它不是一般的。可能這是我的錯,我宣佈了一個誤導性的小問題。無論如何檢查出http://stackoverflow.com/questions/7680442/executing-code-in-overloaded-constructor-prior-to-calling-this/7687567#7687567這有點演變您的解決方案 –

5

工廠方法在同伴對象:

object SearchData { 
    def apply(xml: Node) = new SearchData(xml) //Added to provide uniform factories 
    def apply(url: URL) = { 
    try { 
     new SearchData(XML.load(url)) 
    } catch { 
     case _ => new SearchData(<results/>) 
    } 
    } 
} 

//Example 
val sd = SearchData(new URL("http://example.com/")) 

它不僅簡化了設計,但你可以抽出new關鍵字。

+1

我不明白它是如何簡化設計。它還會迫使你通過根據場景構建具有和不具有'new'關鍵字的對象來引入不一致性,或者違反DRY規則併爲類中的所有構造函數創建伴隨別名,包括主要構造函數,以便可以不使用「新建」總是。然而,你仍然需要用'new'構建類庫。 –

+0

實際上這個模式在scala庫中很常見,並自動實現了case類。所以_inconsistency_已經存在了。再加上構造函數在大多數情況下對客戶端講得太多的強大缺點,即結果的確切類型和新創建的事實。一家工廠不值得一直做,但是它們通常很方便,雖然它讓我感到困擾,但我不會因此而停下腳步。我深深地記得Delphi所在的構造函數和靜態函數,其中的調用方式與客戶端相同。 –

+0

我完全同意你的意見。實際上,[Kotlin](http://confluence.jetbrains.net/display/Kotlin/Classes+and+Inheritance)他們通過擺脫'new'關鍵字來解決這個問題。這對我來說很奇怪,斯卡拉人在這裏看不到問題。 –

3

雖然didierd的解決方案解決了聲明的問題,並且有點接近這個問題,但在調用this之前必須執行幾條語句時仍不能解決問題。這一次提供了一個通用的方法來所有的場景:

class SearchData(xml: Node) { 
    def this(url: URL) = this { 
    println(url) 
    try { 
     XML.load(url) 
    } catch { 
     case _ => <results/> 
    } 
    } 
} 

的這裏訣竅是,this送入與執行身體匿名函數,你被允許做任何事情的結果。

但是這隻能當你有一個單參數主要構造 - 在其他情況下,你將不得不推出Tuple爲基礎的解決方法:

class SearchData(xml: Node, valid: Boolean) { 
    def this(url: URL) = this { 
    println(url) 
    try { 
     (XML.load(url), true) 
    } catch { 
     case _ => (<results/>, false) 
    } 
    } 
    def this(t: (Node, Boolean)) = this(t._1, t._2) 
} 
+0

我想我的評論涵蓋了你的第一個案例與println。但你對第二種情況說得很好。 –

相關問題