Search code examples
kotlingenericscontravariance

Kotlin generic functions and contravariance


I cannot get my head around a seemingly easy problem. I have Reply class, which can contain different response types - Views:

interface View
data class NiceView(val name: String) : View

class MyReply<T : View>(view: T)

Now, I'd like to write a function that accepts a command and returns an appropriate view based on the command:

fun <T : View> handle(command: Command): Reply<T> {
   return Reply(NiceView(""))
}

I can see two issues here:

  1. I get this weird error on the return type Reply<T>, but this only happens in this toy example and not my production code:

    Type argument is not within its bounds.
    Expected: View
    Found: T
    
  2. Error when returning Reply(). This is the thing that is killing my brain and this is what I'm seeing in my production code:

    Type mismatch.
    Required: T
    Found: NiceView
    Type mismatch.
    Required: Reply<T>
    Found: Reply<NiceView>
    Type mismatch.
    Required: View
    Found: NiceView
    

I did try messing around with co- and contravariance using in and out keywords but to no avail. Could someone point me in the right direction here?


Solution

  • fun <T : View> handle(command: Command): Reply<T> { does not mean a function that "accepts a command and returns an appropriate view." It means "a function that accepts a type of view -- and a command -- and returns a reply of that type of view." The caller of handle can choose whatever type of View it wants to get, which is not what you want -- nor what you've implemented, since the user might want something other than NiceView.

    The appropriate type of the handle function in this code, given your stated goal, is

    fun handle(command: Command): Reply<*>