Home > Software design >  Why do I get "Incompatible Types" error using Kotlin "is" opeator
Why do I get "Incompatible Types" error using Kotlin "is" opeator

Time:10-15

I have been experimenting with obtaining the type of a variable in Kotlin, and I find that can do this:

fun main(args: Array<String>) {
    var num1: Short = 1
    var num2 = 100000
    var num3 = 1000000000000
    var num4 = 3.14
    val numList: List<Any> = listOf(num1, num2, num3, num4)

    for(num in numList) {
        if (num is Short) {
            println("Short: $num")
        } else if (num is Int) {
            println("Int: $num")
        } else if (num is Long) {
            println("Long: $num")
        } else {
            println("$num not in listed types")
        }
    }
}

Output:
Short: 1
Int: 100000
Long: 1000000000000
3.14 not in listed types

... But I cannot do this:

fun main(args: Array<String>) {
    var num2 = 100000
    if (num2 is Long) {
        println("Long: $num2")
    } else {
            println("$num2 not in listed types")
        }
}


Output: 
    Kotlin: Incompatible types: Long and Int

Why? What is the difference?

CodePudding user response:

Notice that the elements in the numList have the compile time type Any:

val numList: List<Any> = listOf(num1, num2, num3, num4)
                  ^^^

In other words, num here is of type Any:

for(num in numList) {
    ^^^

Checking whether num actually stores a Long is allowed, because the compiler only knows that its type is Any. It could actually store a Long at runtime.

On the other hand, when you declare and initialise num2, its type is inferred to be Int, because 100000 is an Int literal. The compiler knows that num2 can never store a Long at runtime because its type is Int.

If you use the Long literal 100000L, then your code would compile, and you will get a warning saying that num2 is Long is always true.

CodePudding user response:

In the second case the compiler knows that the check can't succeed, because it knows num2 is Int, so it can't be Long. In the first case it does not know what is the type of num (it is Any), because numList contains objects of various types, so the check is allowed.

In other words, it makes sense to check whether some animal is a dog. However, it does not make sense to check if some cat is a dog.

CodePudding user response:

That is because the compiler understands in the second version that num2 can only be an Int and thus the error.

In the first version, you are testing num which may be basically anything (mind the List<Any> type) and thus the compiler has no way to tell you that the types are not compatible. You will have the same issue with the following code (a changed version of your first example):

fun main() {
    var num2 = 100000
    val numList: List<Int> = listOf(num2)

    for(num in numList) {
        if (num is Short) {
            println("Short: $num")
        } else if (num is Int) {
            println("Int: $num")
        } else if (num is Long) {
            println("Long: $num")
        } else {
            println("$num not in listed types")
        }
    }
}
  • Related