4

Suppose I have the following function definition.

fun<T> parse(a: Any): T = when (a) {
    is String -> a
    else -> false
}

I guessed it should be valid. However, the IntelliJ IDEA linter shows a type mismatch error

Linter error

That being said, I would change the return type of my parse function to Any, right? So that, what is the difference between using Any type and Generics in Kotlin? In which cases should use each of those?

I did read the following question but not understood at all about star-projection in Kotlin due to the fact I am quite new.

Yajairo87
  • 345
  • 1
  • 8
  • 25

3 Answers3

3

Your return type it defined as T, but there is nothing assuring that T and a:Any are related. T may be more restrictive than Any, in which case you can't return a boolean or whatever you provided for a.

The following will work, by changing the return type from T to Any:

fun<T> parse(a: Any): Any = when (a) {
    is String -> a
    else -> false
}

Any alternate option, if you really want to return type T:

inline fun<reified T> parse(a: Any): T? = when (a) {
    is T -> a
    else -> null
}
dillius
  • 506
  • 4
  • 12
2

Your example does not use T and thus it's nonsense to make it generic anyways.

Think about this: As a client you put something into a function, e.g. an XML-ByteArray which the function is supposed to parse into an Object. Calling the function you do not want to have it return Any (Casting sucks) but want the function return the type of the parsed object. THIS can be achieved with generics:

fun <T> parse(xml: ByteArray): T {
     val ctx: JAXBContext = JAXBContext.newInstance()
     val any = ctx.createUnmarshaller().unmarshal(ByteArrayInputStream(xml))
     return any as T
}

val int = parse<Int>("123".toByteArray())
val string = parse<String>("123".toByteArray())

Look at the method calls: You tell with generics what type is expected to be returned. The code is not useful and only supposed to give you an idea of generics.

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
1

I guessed it should be valid

Why would it be? You return a String in one branch and a Boolean in the other. So the common type for the entire when expression is Any and that's what the compiler (and IDEA) says is "found". Your code also says it should be T (which is "required").

Your generic method should work for any T, e.g. for Int, but Any isn't a subtype of Int and so the code isn't valid.

So that, what is the difference between using Any type and Generics in Kotlin?

This is like asking "what is the difference between using numbers and files": they don't have much in common in the first place. You use generics to write code which can work with all types T (or with all types satisfying some constraint); you use Any when you want the specific type Any.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487