2011-09-19 118 views
1

我相信在Scala中,就像在Java中一樣,子類字段在超級構造函數執行後被初始化。鑑於此,我努力確定如何最好地創建可以在我的子類中初始化但在我的抽象父類的構造函數中進行驗證(或用於驗證其他字段)的「抽象字段」。舉個什麼行不通一個簡單的例子:如何驗證Scala抽象父對象中的子類字段?

abstract class ApiClient(contentType: String) { 
    val supportedContentTypes: List[String] 
    if (!(supportedContentTypes contains contentType)) { 
    throw new RuntimeException("Type " + contentType + " not supported") 
    } 
} 

class FacebookClient(contentType: String) extends ApiClient(contentType) { 
    override val supportedContentTypes = List("text/xml", "application/xml") 
} 

val api = new FacebookClient("text/xml") // Throws NullPointerException 

對Java這個問題是討論得最多的(如herehere)和一般的答案是把「抽象田」在父類的構造函數。這個建議對於Scala是否也適用,或者我錯過了一個更好的選擇?

要遵循斯卡拉這種方法,我的代碼是這樣的:

abstract class ApiClient(contentType: String, supportedContentTypes: List[String]) { 
    if (!(supportedContentTypes contains contentType)) { 
    throw new RuntimeException("Type " + contentType + " not supported") 
    } 
} 

class FacebookClient(contentType: String) extends ApiClient(
    contentType, 
    List("text/xml", "application/xml")) { 
} 

val api = new FacebookClient("text/xml") // Runs! 

這是最好的方法?我還沒有看到任何相反的例子,但加載這樣的超級構造函數並不「聞」我。任何想法感激地收到!

回答

2

我認爲,最簡單的解決方案是讓supportedContentTypesFacebookClient懶:

class FacebookClient(contentType: String) extends ApiClient(contentType) { 
    override lazy val supportedContentTypes = List("text/xml", "application/xml") 
} 

這應該按預期工作。


您還可以使用抽象方法 - 它也應該工作得很好。但與Java相比,涉及更少的語法。您通常需要將val更改爲def,您就完成了。

+0

謝謝tenshi!這兩個選項都很好地工作。 –

相關問題