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