I believe that in Scala, like in Java, subclass fields are initialized after the super constructor has executed. Given this, I'm struggling to identify how best to create "abstract fields" that can be initialized in my subclass but validated (or used for validation of other fields) in the constructor of my abstract parent class. To give a simple example of what doesn't work:
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
This question is much-discussed for Java (e.g. here and here) and the general answer is to put the "abstract fields" in the parent class's constructor. Does this advice hold true for Scala too, or is there a neater alternative I'm missing?
To follow this approach with Scala, my code would look like this:
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!
Is this the best approach? I haven't seen any examples to the contrary but loading up the super constructor like this doesn't "smell" great to me. Any thoughts gratefully received!