Есть ли способ объявить расширение области видимости стороннего класса библиотеки kotlin?

Я пытаюсь собрать программу с помощью Jetbrain/Exposed в виде библиотеки ORM и TornadoFX, который является оболочкой версии Kotlin для JavaFX в качестве 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)

    ...
}

И вот проблема в том, что оператор setValue а также getValue для делегата от Exposed объявлен в Entity учебный класс

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 ответ

Решение

Вы можете сделать это, ограничив тип, с которым может использоваться делегат, до Entity,

Это можно сделать, заменив thisRef: Any? с thisRef: Entity<ID> и зовет getValue расширение в thisRef.run { ... } блок, который обеспечивает Entitiy<ID> приемник следующим образом:

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()
}
Другие вопросы по тегам