noob here - why don't these match?
# announcements
d
noob here - why don't these match?
m
Because “registerCallbacks” might call the function with something that is not a
CardReaderStatus
.
d
But is is looking for Any?
Is there a clever way to do this with generics?
m
It might be a bit more clear if you send a lambda instead. Calling it with
{ success(it) }
would kinda be equivalent, right? But that doesn’t work, because
it
is of type
Any?
, not
CardReaderStatus
No, I don’t think so. It’s just a type error any way you look at it.
Functions are contravariant in their arguments. This means that the argument type must be of type
Any?
or a super type of it (which there are none of in this case). So the variance goes the opposite way of what you think here 🙂
d
can one reverse the variance?
s
Alas, no. An ‘in’ paramater is contravariant at best, invariant at worst
a
The issue is that code inside registerCallbacks might invoke you lambda with an argument of type Any?, but your lambda will only accept an argument of type CardReaderStatus
d
now I am starting to understand how it works a little more - thank you
I was dreaming that it would work how I wanted it to 😜
but now I see that it might remove some safety mechanisms
a
We've all been there 😉
👍 1
m
Took a lot of time for me to wrap my head around contravariance, and why function arguments are contravariant 😛
s
I look at sub-class/base-class in this way: It is all about assignability. A subclass var can be assigned to a base-class var, not vice versa. When function returns a value of a sub-type, its value can get assigned to a var of a super-type: Co-variant; the assignability ‘points’ in the same direction. But a function parameter of a super-type gets assigned a value from a provided argument of a base-type. Contra-variant; the assignability ‘points’ in the opposite direction.
3
Copy code
interface Function<in A, out R> {
    fun call(a: A): R 
}
❤️ 1
d
thank you everyone 🙂