2017-07-13 115 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