Question on covariance. Container is covariant on ...
# getting-started
s
Question on covariance. Container is covariant on T but for this case i ignored out modifier on T and as expected processContainer1 fails at compile time ( required<Number> but found <Int>). Just wondering about processContainer which ensures type safety as well. Is there any reason why "out" would be preferred over T : Number?
Copy code
class Container< T : Number > (private var value : T ) {
    fun getContainedValue() : T = value
}

fun <T : Number > processContainer( container : Container<T> ) {
    container.getContainedValue()
}

fun processContainer1( container : Container<Number> ) {
    container.getContainedValue()
}

fun main(args: Array<String>) {

    val intContainer = Container(2)

    processContainer( intContainer )
    processContainer1( intContainer )  // Errors
}
m
You can surround your code in triple backticks (```) to format it.
s
Thx, updated
d
The difference is that with a type parameter you are able to capture the actual type of the container. That way you would be able to call a potential
container.setValue(T)
from inside
processContainer
, provided you had gotten a
T
out of the container beforehand. If you declare the parameter as
out Number
you cannot put anything in, only take
Number
out.
Example:
Copy code
fun <T : Number> processContainer(container: Container<T>) {
    val t: T = container.getValue()
    val updatedT: T = doStuffWithT(t)
    container.setValue(t)
}
You cannot do that with
Container<out Number>
.
s
Assuming, you meant container.setValue( updatedT) but assuming my Container is immutable and doesn't support "in"
would you say both approach "out" and "T:Number" achieves the same purpose? Except that with "out" i can look at the class and understand covariance
d
If your container is "immutable and doesn't support in", then you should just use declaration site variance and declare it as
class Container<out T>
. That way you have the
out
implicitly everywhere it's used.
👍 1
s
Ok got it, thanks