有没有办法向第三方库kotlin类声明范围扩展?

时间:2018-04-27 04:41:42

标签: kotlin kotlin-exposed

我正在尝试使用Jetbrain/Exposed作为ORM库和TornadoFX的程序构建,这是JavaFX的kotlin版本包装器作为UI Framework。 存在一个问题,即实体的类属性由Exposed委托。

object Paintings: UUIDTable() {
    ...
    val description = text("description").default("")
    ...
}

class Painting(id: EntityID<UUID>) : UUIDEntity(id) {
    ...

    var description by Paintings.description

    ...
}

我还想创建一个委托给JavaFX这样的属性的属性

class Painting(id: EntityID<UUID>) : UUIDEntity(id) {
    ...

    var description by property<String>()
    fun descriptionProperty() = getProperty(Painting::description)

    ...
}

这里存在冲突,所以我试图建立一个自己的委托类来包装两个框架的委托。可以通过中缀函数扩展来构建可以包装两个框架的委托的东西。

class Painting(id: EntityID<UUID>) : UUIDEntity(id) {
    ...

    var description by Paintings.description notify property<String>()
    fun descriptionProperty() = getProperty(Painting::description)

    ...
}

以下问题是,来自Exposed的委托的运算符setValuegetValueEntity

中声明
open class Entity<ID:Comparable<ID>>(val id: EntityID<ID>) {
    ...

    operator fun <T> Column<T>.getValue(o: Entity<ID>, desc: KProperty<*>): T = 
        lookup()

    operator fun <T> Column<T>.setValue(o: Entity<ID>, desc: KProperty<*>, value: T) {...}

如果我声明了一个包装类,它就无法访问Column类的Entity的委托运算符

//Global Extension instead of scoped to `Entity`
infix fun <T> Column<T>.notify(fxProperty: PropertyDelegate<T>) {
    return DelegateWrapper(this,fxProperty)
}

class DelegateWrapper<T>(val column: Column<T>, val fxProperty: PropertyDelegate<T>) {

    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return column.getValue(...)  <-cannot resolve getValue
    }

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

作为一个工作,我想我必须构建一个UUIDEntity的子类,并将这些扩展添加为成员扩展和嵌套类以使其工作。

1 个答案:

答案 0 :(得分:1)

您可以通过将代理人可以使用的类型限制为Entity来实现。

这可以通过将thisRef: Any?替换为thisRef: Entity<ID>并在提供getValue接收方的thisRef.run { ... }块中调用Entitiy<ID>扩展名来完成,如下所示:< / p>

class DelegateWrapper<T>(val column: Column<T>, val fxProperty: PropertyDelegate<T>) {

    operator fun <ID : Comparable<ID>> getValue(
        thisRef: Entity<ID>,  // <-- here
        property: KProperty<*>
    ): String =
        thisRef.run { column.getValue(thisRef, property) }  

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) = TODO()
}