2011-09-19 64 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!这两个选项都很好地工作。 –

相关问题