I am trying to get some generic classes to work, but I have not been able to make them compile. I have a generic Container class, in which I want to store an item and I have another generic class, which stores an item in the Container class:
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
}
}
(I know that it is bad practice to use null in Scala, but here I sadly do not have much of a choice.)
First the Container myContainer should be initialized with some default values (in this case null) by the setUpContainer command. After that I want the same variable myContainer to hold another container with an actual item. But I get an error on the item in the FillContainer command in MyGenericClass:
type mismatch; found : A required: Null
and I don´t quite understand why. If I assign the return value of FillContainer immediately to the variable myContainer like so:
def fill(item: A) {
var myContainer = Container.FillContainer(item)
}
it works perfectly fine. What is the difference between assigning the value immediately and reassigning it later?
Also if I do not use generics and use a String instead it does not complain either.
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
}
}
Does anyone know what might cause this behaviour and how to fix it, so I can use the generic classes the same way as the String classes (i.e. First initializing the Container in a variable and after that overwriting the variable with a Container with an actual item)? Thank you in advance.
var myContainer = Container.setUpContainer()
The type of this is not Container[A]
.
setUpContainer
returns a Container[X]
for any X
you choose (you have confusingly named X
as A
in the method definition of setUpContainer
, but it is completely unrelated to the A
of your item
).
Type-inference can only work if there is a starting point (usually a parameter type or the expected return type).
Try
var myContainer = Container.setUpContainer[A]()
or
var myContainer: Container[A] = Container.setUpContainer()