I'm trying to understand what's going on with the following code snippet (extracted from a larger project), in which I manipulate a value returned from a Java superclass. The value has type T
, unbounded in Java, so it is mapped (I guess) to a platform type T!
which I am treating as if it where a T?
.
when (val value = node.getConcentration(molecule)) { // it's a Java method returning an unbounded generic T
is Number -> value.toDouble()
is String -> value.toDouble()
is Time -> value.toDouble()
null -> 0.0 // null has been ruled out, now Kotlin should smart-cast
else -> throw IllegalStateException(
"Expected a numeric value in $molecule at node ${node.id}, " +
"but $value of type ${value::class.simpleName} was found" // THIS IS THE RELEVANT LINE
)
}
I would expect this to work, but I get an error on the type lookup: Expression in a class literal has a nullable type 'T', use !! to make the type non-nullable
. It looks to me like Kotlin does not understand that since the null
case has ben ruled out, the runtime type must be a subclass of Any
.
However, it gets stranger:
when (val value = node.getConcentration(molecule)) {
is Number -> value.toDouble()
is String -> value.toDouble()
is Time -> value.toDouble()
null -> 0.0 // null has been ruled out, now Kotlin should smart-cast
else -> throw IllegalStateException(
"Expected a numeric value in $molecule at node ${node.id}, " +
"but $value of type ${value!!::class.simpleName} was found" // THIS IS THE RELEVANT LINE
)
}
This compiles, but besides being ugly, this one raises (correctly, IMHO) a warning: Unnecessary non-null assertion (!!) on a non-null receiver of type T
-- but this means that the smart casting is work as expected!
I am currently solving as follows:
when (val value = node.getConcentration(molecule)) {
is Number -> value.toDouble()
is String -> value.toDouble()
is Time -> value.toDouble()
null -> 0.0
else -> throw IllegalStateException(
"Expected a numeric value in $molecule at node ${node.id}, " +
"but $value of type ${value.let { it::class.simpleName }} was found"
)
}
This one compiles with no warning, and it is all in all a tolerable amount of boilerplate, but I can't find any reason for value::class.simpleName
for raising errors, especially given that if I enforce non-nullability I get an expected warning.
Does anyone understand what's going on here? Is this a bug in Kotlin? I could not find any specific reference to this issue (by the way I'm on 1.4.21).
Aucun commentaire:
Enregistrer un commentaire