2017-07-13 124 views
2

您可以將財產委託給Kotlin中的其他財產嗎?我有以下代碼:將財產委託給其他財產

class SettingsPage { 
    lateinit var tagCharacters: JTextField 
    lateinit var tagForegroundColorChooser: ColorPanel 
    lateinit var tagBackgroundColorChooser: ColorPanel 

    var allowedChars: String 
    get() = tagCharacters.text 
    set(value) = tagCharacters.setText(value) 

    var tagForegroundColor by tagForegroundColorChooser 
    var tagBackgroundColor by tagBackgroundColorChooser 
} 

爲了獲得財產委託,我宣佈了以下兩個擴展功能:

operator fun ColorPanel.getValue(a: SettingsPage, p: KProperty<*>) = selectedColor 
    operator fun ColorPanel.setValue(a: SettingsPage, p: KProperty<*>, c: Color?) { selectedColor = c } 

不過,我想寫的是類似如下:

class SettingsPage { 
    lateinit var tagCharacters: JTextField 
    lateinit var tagForegroundColorChooser: ColorPanel 
    lateinit var tagBackgroundColorChooser: ColorPanel 

    var allowedChars: String by Alias(tagCharacters.text) 
    var tagForegroundColor by Alias(tagForegroundColorChooser.selectedColor) 
    var tagBackgroundColor by Alias(tagBackgroundColorChooser.selectedColor) 
} 

這可能做Kotlin?我如何編寫Alias類?

回答

5

是的,這是可能的:你可以使用一個bound callable reference爲您在別名存儲的屬性,然後Alias實施將看起來像這樣:

class Alias<T>(val delegate: KMutableProperty0<T>) { 
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T = 
     delegate.get() 

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { 
     delegate.set(value) 
    } 
} 

和使用:

class Container(var x: Int) 

class Foo { 
    var container = Container(1) 
    var x by Alias(container::x) 
} 

要引用同一實例的屬性,請使用this::someProperty

+0

是否可以定義在'KProperty0',其中使用的擴展功能簡單地說就是'var x by container :: x'? – breandan

+1

@Breandan:'operator fun KProperty0 .getValue(thisRef:Any?,property:KProperty <*>)= get();運營商樂趣 KMutableProperty0 .setValue(thisRef:任何?,屬性:KProperty <*>,值:T)=設置(值);' –

+0

謝謝!不幸的是,這不支持委託Java類的合成屬性。使用var tagBackgroundColor by tagBackgroundColorChooser :: selectedColor在原始示例中定義這些擴展會導致一個錯誤,即Unsupported [對Java get/set方法的合成擴展屬性的引用]。 – breandan