2017-07-06 196 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