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")
}
}
}