2017-07-06 177 views
0

我有一种情况,我需要在Kotlin的类中定义一个静态属性,并且当它编译为Javascript时,它已成为该类上的一个真正的静态字段。在这种情况下,伴侣对象不起作用。如何在Kotlin for 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中设置像这样的静态字段?

+0

如果您编译到JVM有一个'@ JvmStatic'注解。也许这有一个相当于JS的? – Mibac

+1

相关问题:https://youtrack.jetbrains.com/issue/KT-18891 – bashor

+0

您可以在类上声明静态变量,但不能声明抽象静态变量。哪有这回事。 – Joshua

回答

0

眼下我们没有直接的办法做到这一点,所以我创建问题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

相关问题