【问题标题】:Is there any way to declare a scope extension to third party library kotlin class?有没有办法声明第三方库 kotlin 类的范围扩展?
【发布时间】:2018-04-27 04:41:41
【问题描述】:

我正在尝试使用 Jetbrain/Exposed 作为 ORM 库和 TornadoFX 构建程序,这是作为 UI 框架的 JavaFX 的 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 类中

//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 的子类并将这些扩展添加为成员扩展和嵌套类以使其工作。

【问题讨论】:

  • 你能具体告诉我你想扩展实体中的哪个函数或显示一些代码吗?
  • @notionquest 好的,我刚刚更新了更多详细信息

标签: kotlin kotlin-exposed


【解决方案1】:

您可以通过将委托可以使用的类型限制为 Entity 来做到这一点。

这可以通过将thisRef: Any? 替换为thisRef: Entity&lt;ID&gt; 并在提供Entitiy&lt;ID&gt; 接收器的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()
}

【讨论】:

  • 感谢您的回答。这对我有用。但我仍然希望 kotlin 能够尽快支持从外部添加成员扩展。XD
猜你喜欢
  • 2021-03-17
  • 2018-03-11
  • 2019-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
相关资源
最近更新 更多