Есть ли способ объявить расширение области видимости стороннего класса библиотеки 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()
}