Как вывести правильный тип элемента для пустой инвариантной коллекции (например, Set) - PullRequest
0 голосов
/ 13 февраля 2020

В классе case мне пришлось изменить один аргумент конструктора с String на Set[String]. Для обратной совместимости я добавил объект-компаньон с перегруженной функцией apply.

case class OldClass (x: String, y: Set[String] = Set()) {}

case class NewClass(x: Set[String], y: Set[String] = Set()) {}

object NewClass {
    def apply(x: String): NewClass = NewClass(Set(x), Set[String]())
    def apply(x: String, y: Set[String]): NewClass = NewClass(Set(x), y)
}

Теперь это работает:

val c = NewClass("xxx", Set[String]())

Но как я могу заставить эту работу работать:

val c = NewClass("xxx", Set())

Мне это нужно, потому что у меня есть код, который полагается на возможность создания NewClass, подобного этому

Я получаю сообщение об ошибке:

overloaded method value apply with alternatives (x:String) <and> (x: String,y: Set[String]) cannot be applied to (String, scala.collection.immutable.Set[Nothing])

1 Ответ

2 голосов
/ 13 февраля 2020

Проблема в том, что конструктор Set() возвращает значение типа Set[Nothing], которое не является Set[String]. Чтобы сделать эту работу именно так, как вы хотите, вы можете использовать не очень надежный, но рабочий подход, добавив еще один конструктор, который фактически позволяет Set [Nothing]:

  case class NewClass(x: Set[String], y: Set[String]) {}

  object NewClass {
    def apply(x: Set[String]): NewClass = NewClass(x, Set.empty[String])
    def apply(x: String): NewClass = NewClass(Set(x), Set[String]())
    def apply(x: String, y: Set[String]): NewClass = NewClass(Set(x), y)
    def apply(x: String, y: Set[Nothing], z: Unit = ()): NewClass = NewClass(Set(x), Set.empty[String])
  }

  val c = NewClass("xxx", Set())

Обратите внимание, что z: Unit = () параметр по умолчанию добавляется только и только чтобы отличить guish эти два конструктора после стирания универсального типа и параметр по умолчанию y = Set.empty[String] был удален, потому что первый конструктор фактически восстанавливает такой синтаксис. Я не рекомендую использовать этот подход в реальном коде, потому что это довольно нелогичный взлом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...