Does anyone know why this doesn't compile? If I u...
# announcements
m
Does anyone know why this doesn't compile? If I understand correctly: * T is
String
*
in T
means that I can pass T or any of its super classes *
Any
is superclass of
String
* so
Container<in T>
should accept
Container<Any>
right? Instead I get:
Copy code
Type mismatch.
Required :String
Found: Any
right but it f Any is subtype of String, I should be able to pass it right? (EDIT: I replied to a deleted comment)
Java's equivalence of this would be
Container<? super T>
which means
T
or any of its super classes, right?
k
T
is defined as
T : Any?
. So the
Container
might contain nullable types,
methodB
only takes non-null types. You either have to bind
T
as
T : Any
or change
methodB
to allow for nullable types
fun methodB(input: Container<Any?>)
.
fun <T : Any> methodA(target: (Container<T>) -> Unit)
would be another option.
a
Copy code
methodA<Any>(::methodB)
Even this fails because methodB only takes Container<Any> which is not exactly Container<in Any>
What if methodB was given Container<String> why would it accept it, it only will take Container<Any> as by the function definition
Or I might be wrong :p
k
Just to provide a complete example:
Copy code
data class Container<T>(val value: T)

fun methodB(input: Container<Any>) {}

fun <T : Any> methodA(target: (Container<T>) -> Unit) {}

fun main() {
    methodA(::methodB)
}
m
Thanks for the answer. Totally forgot about nullability
However, this also does not compile, with nullability ruled out:
Copy code
data class Container<T: Any>(val value: T)

fun methodB(input: Container<Any>) {

}

fun <T : Any> methodA(target: (Container<in T>) -> Unit) {

}

fun main() {
    methodA<String>(::methodB)
}
k
You have to remove the covariance in
<in T>
and let the compiler do the inference in the main method by removing the explicit type definition.
For reference, you can find these changes in the example I posted above.
m
right, but removing
in T
removes the whole idea of this example
I specified
<String>
here explicitly just to make example more concise
For example, here is more complicated sample that I wanted to avoid to keep it simple:
Copy code
data class Container<T: Any>(val value: T)

fun methodB(input: Container<Any>) {

}

fun <T : Any> methodA(target: (Container<in T>) -> Unit, classOfT: Class<T>) {

}

fun main() {
    methodA(::methodB, String::class.java)
}
k
Wouldn’t this be the correct way of doing so:
Copy code
data class Container<T : Any>(val value: T)

fun methodB(input: Container<out Any>) {}

fun <T : Any> methodA(target: (Container<T>) -> Unit, classOfT: Class<T>) {}

fun main() {
    methodA(::methodB, String::class.java)
}
m
oh I see. And then problem collapses into the same problem that I had with the second snippet (you can't mix those types really).
Thanks!