有什么方法可以声明对第三方库 kotlin class 的范围扩展吗?
Is there any way to declare a scope extension to third party library kotlin class?
我正在尝试使用 Jetbrain/Exposed as ORM library and TornadoFX 构建程序,它是作为 UI 框架的 JavaFX 的 kotlin 版本包装器。
有一个实体的class属性被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 来包装两个框架的 delegated.Maybe 构建可以通过中缀函数扩展包装两个框架的委托的东西。
class Painting(id: EntityID<UUID>) : UUIDEntity(id) {
...
var description by Paintings.description notify property<String>()
fun descriptionProperty() = getProperty(Painting::description)
...
}
问题是来自 Exposed 的委托的运算符 setValue
和 getValue
在 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) {...}
如果我声明一个包装器 class,它就无法访问 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 的子class,并将这些扩展添加为成员扩展并嵌套 class 以使其工作。
您可以通过将委托可以使用的类型限制为 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()
}
我正在尝试使用 Jetbrain/Exposed as ORM library and TornadoFX 构建程序,它是作为 UI 框架的 JavaFX 的 kotlin 版本包装器。 有一个实体的class属性被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 来包装两个框架的 delegated.Maybe 构建可以通过中缀函数扩展包装两个框架的委托的东西。
class Painting(id: EntityID<UUID>) : UUIDEntity(id) {
...
var description by Paintings.description notify property<String>()
fun descriptionProperty() = getProperty(Painting::description)
...
}
问题是来自 Exposed 的委托的运算符 setValue
和 getValue
在 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) {...}
如果我声明一个包装器 class,它就无法访问 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 的子class,并将这些扩展添加为成员扩展并嵌套 class 以使其工作。
您可以通过将委托可以使用的类型限制为 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()
}