Scala дженерики прерывают переназначение на var - PullRequest
0 голосов
/ 16 июня 2020

Я пытаюсь заставить работать некоторые общие c классы, но мне не удалось их скомпилировать. У меня есть общий c контейнерный класс, в котором я хочу сохранить элемент, и у меня есть еще один общий c класс, который хранит элемент в классе контейнера:

final case class Container[A](var item: A) 

object Container {
  def FillContainer[A](item: A): Container[A] = {
    Container(item)
  }

  def setUpContainer[A]() = FillContainer[A](null.asInstanceOf[A])
}
class MyGenericClass[A] {
  def fill(item: A) {
    var myContainer = Container.setUpContainer()
    myContainer = Container.FillContainer(item) //type mismatch; found : A required: Null
  }
}

( Я знаю, что использовать null в Scala - плохая практика, но здесь у меня, к сожалению, нет особого выбора.)

Сначала контейнер myContainer должен быть инициализирован некоторыми значениями по умолчанию (в данном случае null ) командой setUpContainer. После этого я хочу, чтобы та же переменная myContainer содержала другой контейнер с фактическим элементом. Но я получаю сообщение об ошибке в элементе команды FillContainer в MyGenericClass: type mismatch; found : A required: Null, и я не совсем понимаю, почему. Если я немедленно присвою возвращаемое значение FillContainer переменной myContainer, например:

def fill(item: A) {
  var myContainer = Container.FillContainer(item)
}

, он будет работать отлично. В чем разница между присвоением значения сразу и его переназначением позже?

Также, если я не использую дженерики и использую вместо них String, он тоже не жалуется.

final case class StringContainer(var item: String) 

object StringContainer {
  def FillContainer(item: String): StringContainer = {
    StringContainer(item)
  }

  def setUpContainer() = FillContainer(null)
}


class StringClass {
  def fill(item: String) {
    var myContainer = StringContainer.setUpContainer()
    myContainer = StringContainer.FillContainer(item) //no problem
  }
}

Кто-нибудь знает, что может вызвать такое поведение и как его исправить, поэтому я могу использовать классы generi c так же, как классы String (т.е. сначала инициализировать контейнер в переменной и после этого перезапись переменной с помощью контейнера фактическим элементом)? Заранее спасибо.

1 Ответ

2 голосов
/ 16 июня 2020
var myContainer = Container.setUpContainer()

Тип не Container[A].

setUpContainer возвращает Container[X] для любого X по вашему выбору (вы неправильно назвали X как A в определении метода setUpContainer, но это совершенно не связано с A вашего item).

Вывод типа может работать только при наличии начальной точки (обычно это тип параметра или ожидаемый тип возвращаемого значения).

Попробуйте

  var myContainer = Container.setUpContainer[A]()

или

  var myContainer: Container[A] = Container.setUpContainer()
...