2015-11-02 2 views
0

Предположим следующую пару классов:Проверка полученные аргументы класса в Scala

class A(arg:String) 

class B(argList:Vector[String]) extends A(argList.first) 

Я хочу, чтобы иметь возможность проверить argList порожняком, прежде чем предоставлять конструктор базового класса с первым элементом. К сожалению, размещение этой проверки в конструкторе по умолчанию для B (например, через require, как показано here) является слишком запоздалым, так как сначала нужно вызвать конструктор базового класса.

Это, вероятно, более общий вопрос ООП, но решение, скорее всего, будет специфичным для Scala.

+0

В Java, делать что-либо в конструкторе до вызова супер конструктор дает ошибку во время компиляции. Другими словами, суперконструктор ** должен быть первым утверждением в дочернем конструкторе (он называется неявным, если опущен). Я не думаю, что в Scala есть обходной путь. Это решение Java. –

ответ

4

Что вы ожидаете пройти, если argList пуст? В любом случае вы могли бы просто использовать следующее:

class B(argList:Vector[String]) extends A(argList.headOption.getOrElse("your default string here") 
+0

Суть этого и решений @Shadowlands - метод 'headOption', о котором я не знал. Спасибо вам за вход. Собираюсь принять это исключительно по тайным причинам. – Jason

4

Один из способов борьбы с этим - через сопутствующий объект. Вы можете отметить конструктор для B как частные, чтобы гарантировать никто не может обойти проверку, а затем добавить подходящий apply метод объекта-компаньона, который предварительно проверяет значение входного (ы):

class A(arg:String) 

class B private(argList:Vector[String]) extends A(argList.head) 

object B { 
    def apply(argList:Vector[String]): B = argList.headOption.map(_ => new B(argList)).getOrElse(throw new RuntimeException("Oops")) 
} 

Использование примеры:

scala> B(Vector("foo", "bar")) 
res2: B = [email protected] 

scala> B(Vector()) 
java.lang.RuntimeException: Oops 
    at B$$anonfun$apply$2.apply(<console>:24) 
    ... 

Обратите внимание, что для простоты, я просто бросить исключение при обработке некорректных данных, но, вероятно, попробовать другой способ обработки этой ситуации (значение по умолчанию на @ ответ Золтан является одним из таких способов).

1

Именно поэтому в большинстве мест конструкторы заменяются заводскими объектами. В Scala идиоматично использовать сопутствующий объект в качестве таких заводов.

class A(arg: String) 

abstract class B(arg: String) extends A(arg) { 
    def argList: IndexedSeq[String] 
} 

object B { 
    case object Empty extends B("") { 
    def argList = IndexedSeq.empty 
    } 
    case class NonEmpty private[B](argList: Vector[String]) extends B(argList.head) 

    def apply(argList: Vector[String]) = 
    if (argList.isEmpty) Empty else NonEmpty(argList) 

    def unapplySeq(b:B): Option[IndexedSeq[String]] = b match { 
    case Empty ⇒ Some(IndexedSeq.empty) 
    case NonEmpty(args) ⇒ Some(args) 
    } 
} 

вы могли убедиться, что

B(Vector()) == B.Empty 

B(Vector("x", "y")).isInstanceOf[B.NonEmpty] 
Смежные вопросы