yonBav
yonBav

Reputation: 1915

Kotlin T value cannot be assigned with function that returns any

so i have this code that won't compile.

suspend fun <T> GetContent(call: ApplicationCall) : T {
    var requestContent: T? = null

    try {
        requestContent = call.receive()
    }
    catch (exception: Exception) {
        println(exception)
    }
}

The problem is that call.receive() returns any so i get an error saying "T? is not a subtype of Any".

So I Read about Any and the key concept is in the first 2 line of the documentation

"The root of the Kotlin class hierarchy. Every Kotlin class has Any as a superclass."

But it creates this paradox where T really does not inherits from Any because its not a class but in the other hand it will surly be a class when using it.

I'm new to Kotlin so I guess I just not fully understand the Any concept or not fully understand something in the Generic concept.

Upvotes: 0

Views: 478

Answers (2)

gidds
gidds

Reputation: 18537

To address the point about Any:

This is about nullability.

The documentation you found is talking about classes, but not about types; the distinction is subtle but important.  (Even in Java, those things aren't quite the same; for example, List is a class, but List<String> is a type.)

In Kotlin, nullability is part of the type system.  So while Any is the topmost class (corresponding to Java's Object), both Any and Any? are types: the difference being that only the latter can hold null.  This makes Any a subtype of Any?, and Any? the topmost type.

Your example has the type T?, which is nullable — and so not a subtype of Any, which isn't.

However, that's not the only thing going in your question; in the code you quoted, T? would have to be a supertype of Any — which it's clearly not.  (I'm also puzzled by trying to parameterise only the return value.  How is the compiler supposed to infer the actual type of T in each call?)

Upvotes: 1

ich5003
ich5003

Reputation: 838

You probably did Java before, right? Any is the Kotlin equivalent to Javas Object, which means in Kotlin every object implicitly inherits from Any or in other words Any can be used as a placeholder for any possible class.

In your case you could try casting your result, I think this will work:

requestContent = call.receive() as T

This line means, you know, that call.receive() is indeed an Object of class T or a subclass of it. This will throw an error, if this assumption is false.

// Edit: A clearer example of inheritance.

Take the following example, you have a class Animal and two subclasses Dog and Cat. Your inheritance graph looks like this now:

         Animal
        /      \
       /        \
      V          V
     Dog        Cat

So this says: Each cat is an animal and each dog is an animal. But if you have any animal you can't say whether it is a dog or a cat.

In your specific case, Any is the Animal class and f.e. Dog is your T. So T does indeed inherit from Any, but you don't know if it's really a T or maybe something else, but if you know that in this specific case it is T, you can cast it.

Upvotes: 1

Related Questions