Есть ли способ объявить расширение области видимости для библиотеки сторонних библиотек класса kotlin? - PullRequest
0 голосов
/ 27 апреля 2018

Я пытаюсь построить программу с 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)

    ...
}

А вот проблема в том, что оператор setValue и getValue для делегата из Exposed объявлен в Entity class

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

0 голосов
/ 27 апреля 2018

Вы можете сделать это, ограничив тип, с которым может использоваться делегат, до 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()
}
...