Итак, у меня был очень простой класс case:
case class StreetSecondary1(designator: String, value: Option[String])
Это работало отлично. Тем не менее, у меня были места, где я разбирал одну строку в кортеж, который затем использовался для создания экземпляра этого класса case:
def parse1(values: String): StreetSecondary1 = {
  val index = values.indexOf(" ")
  StreetSecondary1.tupled(
    if (index > -1)
      //clip off string prior to space as designator and optionally use string after space as value
      (values.take(index), if (values.size > index + 1) Some(values.drop(index + 1)) else None)
    else
      //no space, so only designator could have been provided
      (values, None)
  )
}
Итак, я хотел реорганизовать все разные места с помощью этого же кода синтаксического анализа в класс case, как это (но это не будет компилироваться):
case class StreetSecondary2(designator: String, value: Option[String]) {
  def this(values: String) = this.tupled(parse(values))
  private def parse(values: String): (String, Option[String]) = {
    val index = values.indexOf(" ")
    if (index > -1)
      //clip off string prior to space as designator and optionally use string after space as value
      (values.take(index), if (values.size > index + 1) Some(values.drop(index + 1)) else None)
    else
      //no space, so only designator could have been provided
      (values, None)
  }
}
Похоже, что возникает проблема с цыпленком/яйцом при добавлении конструктора класса case И с функцией, которая принимает параметр и преобразует их перед вызовом фактического конструктора. Я возился с этим (идя по многим касательным). Затем я прибег к попытке пути сопутствующего объекта:
object StreetSecondary3 {
  private def parse(values: String): (String, Option[String]) = {
    val index = values.indexOf(" ")
    if (index > -1)
      //clip off string prior to space as designator and optionally use string after space as value
      (values.take(index), if (values.size > index + 1) Some(values.drop(index + 1)) else None)
    else
      //no space, so only designator could have been provided
      (values, None)
  }
  def apply(values: String): StreetSecondary3 = {
    val tuple: (String, Option[String]) = parse(values)
    StreetSecondary3(tuple._1, tuple._2)  //Why doesn't .tupled method work here?
  }
}
case class StreetSecondary3(designator: String, value: Option[String])
Что я делаю неправильно в StreetSecondary2? Есть ли способ заставить его работать? Разумеется, должен быть более простой способ, когда мне не нужно добавлять все шаблоны сопутствующих объектов, присутствующие в StreetSecondary3. Есть?
Спасибо за любые отзывы и рекомендации, которые вы можете мне дать.
ОБНОВЛЕНИЕ
Уф! Уже много уроков.
A) метод parse StreetSecondary2 не использует неявный контекст "this" в создаваемом экземпляре класса case (т.е. является статическим методом в терминах Java), поэтому он лучше перемещается в объект-компаньон.
B) К сожалению, при составлении явного сопутствующего объекта для класса case компилятор, предоставляющий "неявный сопутствующий объект", теряется. Метод пополнения (и другие, я угадываю - конечно, пожелал, чтобы был способ сохранить его и увеличить, в отличие от его удаления) содержались в компиляторе, снабженном "неявным сопутствующим объектом" и не предоставляемом в новом явном сопутствующем объекте. Это было исправлено добавлением "extends ((String, Option [String]) = > StreetSecondary) к явному сопутствующему объекту.
C) Здесь обновленное решение (которое также включает более краткий вариант функции синтаксического анализа с благодарностью Габриэле Петронелле):
object StreetSecondary4 extends ((String, Option[String]) => StreetSecondary4) {
  private def parseToTuple(values: String): (String, Option[String]) = {
    val (designator, value) = values.span(_ != ' ')
    (designator, Option(value.trim).filter(_.nonEmpty))
  }
  def apply(values: String): StreetSecondary4 =
    StreetSecondary4.tupled(parseToTuple(values))
}
case class StreetSecondary4(designator: String, value: Option[String])
Это едва лучше с точки зрения шаблона, чем версия StreetSecondary3. Тем не менее, теперь это становится немного более ощутимым из-за того, что явный контекстный контекст стал явным.
