KotlinJS中is运算符为何不遵循继承规则?
KotlinJS中Number继承类的
is判断异常问题 问题场景
我在开发KotlinJS React项目,使用的插件配置:
plugins { kotlin("js") version "1.8.0" }
定义了继承自Number的Percentage类:
class Percentage(private val number: Number) : Number() { override fun toByte() = number.toByte() override fun toChar() = number.toChar() override fun toDouble() = number.toDouble() override fun toFloat() = number.toFloat() override fun toInt() = number.toInt() override fun toLong() = number.toLong() override fun toShort() = number.toShort() override fun toString() = "$number%" }
但执行以下代码时,控制台输出false,尽管IDEA提示“该实例检查始终为true”:
if (value is Percentage) { println(value is Number) }
原因分析
这是KotlinJS底层实现特性导致的:
- 在Kotlin/JVM中,
Number是所有数值类型的父类,继承关系在字节码层面正常体现,is判断符合预期。 - 但在KotlinJS中,
Number会被编译为JavaScript原生Number类型,而自定义继承Number的Kotlin类,最终会被编译成普通JS对象,不会成为原生Number的实例。 - Kotlin的
is运算符在JS平台对应JavaScript的instanceof,后者通过原型链判断类型,自定义类的原型链和原生Number不重合,因此value is Number返回false。
解决方案
改用组合模式替代继承:不再继承
Number,将Number作为成员变量,按需暴露数值转换方法:class Percentage(private val number: Number) { fun toByte() = number.toByte() fun toChar() = number.toChar() fun toDouble() = number.toDouble() fun toFloat() = number.toFloat() fun toInt() = number.toInt() fun toLong() = number.toLong() fun toShort() = number.toShort() override fun toString() = "$number%" }若需要统一判断数值相关类型,可自定义接口或直接检查成员变量类型。
自定义类型判断逻辑:如果必须保留继承关系,可扩展属性实现兼容判断:
val Any.isNumberLike: Boolean get() = this is Number || this is Percentage使用时用
value.isNumberLike替代value is Number。升级Kotlin版本:后续Kotlin版本(如1.9.x及以上)优化了JS平台的
Number继承处理,可尝试升级插件版本到最新稳定版:plugins { kotlin("js") version "1.9.20" }
内容的提问来源于stack exchange,提问作者raven
相关产品推荐
相关产品推荐

