Как установить статическое свойство для класса в Kotlin для Javascript
У меня есть ситуация, когда мне нужно определить статическое свойство для класса в Kotlin, и когда оно скомпилировано в 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
}
Javascript, к которому это компилируется, таков:
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
поле к этому и никогда не назначает его статически MyClass
,
Как я могу установить истинные статические поля, подобные этому, в Kotlin?
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