如何在Kotlin中为Javascript设置类的静态属性

时间:2017-07-06 17:55:34

标签: javascript kotlin kotlin-js-interop

我有一种情况,我需要在Kotlin中的类上定义一个静态属性,当它编译为Javascript使它成为该类的真正静态字段。在这种情况下,伴侣对象不起作用。

例如,如果我有一个抽象类及其实现类,如下所示:

setlocal /?

这个编译的Javascript是这样的:

abstract class MyAbstractClass{
  abstract val id: Int
}

class MyClass: MyAbstractClass(){
  override val id: Int = 1 //I want this to actually be "static" on the MyClass
}

但我需要编译的是:

function MyAbstractClass() {
}

function MyClass() {
  MyAbstractClass.call(this);
  this.id_jz5fma$_0 = 1;
}

Object.defineProperty(MyClass.prototype, 'id', {
  get: function () {
    return this.id_jz5fma$_0;
  }
});

这样function MyAbstractClass() { } function MyClass() { MyAbstractClass.call(this); } MyClass.id = 1; 字段确实在id上确实存在,而无需创建MyClass的新实例。

我尝试过使用随播广告对象,但会创建一个名为MyClass的单独对象/函数,然后将MyClass$Companion字段分配给该字段,并且永远不会将其静态分配给id

如何在Kotlin中设置这样的真实静态字段?

1 个答案:

答案 0 :(得分:1)

目前我们还没有直接的方法,所以我创建了问题https://youtrack.jetbrains.com/issue/KT-18891

作为一种解决方法,您可以编写类似的函数:

inline fun <reified T : Any> addStaticMembersTo(source: Any) {
    val c = T::class.js.asDynamic()
    val ownNames = js("Object").getOwnPropertyNames(source) as Array<String>
    val protoNames = js("Object").getOwnPropertyNames(source.asDynamic().constructor.prototype) as Array<String>

    for (name in ownNames + protoNames) {
        c[name] = source.asDynamic()[name]
    }
}

并使用如下:

class A {
    companion object {
        init {
            addStaticMembersTo<A>(object {
                val bar = 1
                fun foo() {}                
            })
        }
    }
}

甚至使伴侣对象的成员可用作类的静态成员:

class B {
    companion object {
        val bar = 1
        fun foo() {}                

        // should be at the end of companion object
        init {
            addStaticMembersTo<B>(this)
        }
    }
}

这里提供的完整示例: https://try.kotl.in/#/UserProjects/uube1qikg3vsegtnefo0ad0jag/30f1qf87dt5k5vjhciirt4t108