Hello, I am puzzled as I try to do something simpl...
# android
m
Hello, I am puzzled as I try to do something simple in Kotlin and compiler rejects my idea constantly. Not sure if this some Christmas break brain fog and I miss something obvious? Anyone dares to explain what I am doing wrong here?
Copy code
fun interface Mapper<T> {
    suspend fun map(value: String): T
}

fun <R> test(mapper: Mapper<R> = Mapper { it }) {

}
image.png
e
Mapper<out T>
Thats not how generics work. You cannot assign a Mapper of String to a Mapper of R. If someone calls your method like
test<Int>() { ... }
, then that means the compiler allowed code which is impossible to be called
đź‘Ś 1
It wouldn’t even matter what the implementation of that method is, just the signature makes the program catastrophically wrong. If you don’t care about the exact type parameter of the
mapper
parameter then you should represent it as
Mapper<*>
Or if you strongly feel that this is correct you can cast String to R like
Mapper { it as R }
which will generate a (very correct) warning
m
you are right, I forgot that generics do not allow such a thing
I am not sure why it is catastrophically wrong though, in the generic param I define what I would like this mapper to return, so at compile time it is known exactly what this function returns
Mapper<Int> would just implicate that the mapper returns an Int when given a String
what I think that is mainly wrong here is that I thought that a variable declaration done with generics can be assigned with a specific type and this is, like you have mentioned, not how generics work
it works if R is provided explicitly
Copy code
fun interface Mapper<T> {
    suspend fun map(value: String): T
}

fun <R> test(mapper: Mapper<String> = Mapper { it }) {

}
in my head I thought that generic type will work like inheritance here, so if T is Any so I can provide a whatever default
e
@Maciej Pigulski Look at the simple example I posted. At the use site, you specify that this functions type argument is of type
Int
by writing
test<Int>() { ... }
, this means that the parameter
mapper
should be of type
Mapper<Int>
but remember in the default argument of that function (if kotlin compiler did not flag this case) you would be assigning Mapper<String> to Mapper<Int> which would be a runtime failure
The generic type does work with inheritance but when you have some generic constraints