首页 文章

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

提问于
浏览
2

我正在尝试使用Jetbrain/Exposed作为ORM库和TornadoFX进行程序构建,这是JavaFX作为UI Framework的kotlin版本包装器 . 存在一个问题,即实体的类属性由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 class

//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 回答

  • 1

    您可以通过将委托可以使用的类型限制为 Entity 来实现 .

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

    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()
    }
    

相关问题