Как мне проверить подклассовое поле в моем абстрактном родительском объекте Scala? - PullRequest
1 голос
/ 19 сентября 2011

Я считаю, что в Scala, как и в Java, поля подкласса инициализируются после выполнения супер-конструктора.Учитывая это, я изо всех сил пытаюсь определить, как лучше всего создать «абстрактные поля», которые могут быть инициализированы в моем подклассе, но проверены (или использованы для проверки других полей) в конструкторе моего абстрактного родительского класса.Чтобы привести простой пример того, что не работает:

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 (например, здесь и здесь ) и общегоОтвет заключается в том, чтобы поместить «абстрактные поля» в конструктор родительского класса.Применим ли этот совет и к Scala, или мне не хватает другой альтернативы?

Чтобы следовать этому подходу с 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!

Isэто лучший подход?Я не видел примеров обратного, но загрузка супер-конструктора, как этот, не «пахнет» для меня.Любые мысли с благодарностью принимаются!

1 Ответ

2 голосов
/ 19 сентября 2011

Я думаю, что самое простое решение - сделать supportedContentTypes в FacebookClient lazy:

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

Это должно работать как положено.


Вы также можете использовать абстрактный метод - он также должен работать просто отлично.Но, в отличие от Java, здесь используется гораздо меньше синтаксиса.Как правило, вам нужно изменить val на def, и все готово.

...