I am reading and trying to understand Kotlin type projections, sometimes I come up with confusing things like this:
For contravariant type parameters such as
Consumer<in T>
, a star projection is equivalent to<in Nothing>
. In effect, you can’t call any methods that haveT
in the signature on such a star projection. If the type parameter is contravariant, it acts only as a consumer, and, as we discussed earlier, you don’t know exactly what it can consume. Therefore, you can’t give it anything to consume.You can use the star projection syntax when the information about type arguments isn’t important: you don’t use any methods that refer to the type parameter in the signature, or you only read the data and you don’t care about its specific type. For instance, you can implement the
printFirst
function takingList<*>
as a parameter.
What does it mean to contravariant type to have a star projection and how does it come up to
This is also explained in the Kotlin documentation:
Example
We have a class
Foo<T>
with contravariantT
(declaration-site), i.e.Foo
only works as a consumer ofT
:We can use this type in simple generic functions as follows:
(used
F
in order to distinguish from class type parameterT
)This works fine since we use
Foo
as intended: As a consumer ofT
s.Now, your quote simply says that having a parameter of type
con: Foo<*>
instead ofcon: Foo<T>
would have the following effect: "you can't call any methods that haveT
in the signature".Thus, the following fails:
It's not safe to call
accept
with an instance ofF
because we don't know the type ofFoo
(denoted by star projection).