我正在尝试使用Wicket的操作符,这很痛苦.
我最想要的功能是使用一元“”来添加()一个组件.
但是需要在每个MarkupContainer后代的上下文中工作.
使用应该是这样的:
class SomePage() : WebPage() {
init {
// SomePage{} context
+Label("someLabel","Some label")
// instead of this.add(Label("someLabel","Some label"))
+object : StatelessForm<Unit>("someForm") {
init {
// StatelessForm{} context
+Label("fieldLabel","Field label")
+RequiredTextField("someField")
}
}
}
}
是否有可能在没有子类化所有内容的情况下实现它?我想要的一些想象的语法:
extend org.apache.wicket.MarkupContainer {
operator fun<T: Component> T.unaryPlus():T {
// add() is called as a method of a MarkupContainer instance
add(this) // this@MarkupContainer.add(this@unaryPlus)
return this
}
}
> https://kotlinlang.org/docs/reference/extensions.html
> https://kotlinlang.org/docs/reference/operator-overloading.html
最佳答案 在这种情况下使用
unaryPlus
运算符(Component)更难,因为正如一元所暗示的那样,它是一个单操作数运算符(单输入).但是有一种hacky解决方案:
class ExtOf<out T : MarkupContainer>(val self: T) {
companion object {
private val lastConfiguredContainer = ThreadLocal<ExtOf<MarkupContainer>?>()
fun <T : MarkupContainer> configure(container: T, configurer: ExtOf<T>.() -> Any?): T {
val currentLast = lastConfiguredContainer.get()
try {
val newCurrent = ExtOf(container)
lastConfiguredContainer.set(newCurrent)
newCurrent.configurer()
} finally {
lastConfiguredContainer.set(currentLast)
}
return container
}
}
operator fun <T2 : Component> T2.unaryPlus(): T2 {
val container = lastConfiguredContainer.get()
container!!.self.add(this) //TODO throw a nice exception explaining how ot use the `configure`
return this
}
}
fun <T : MarkupContainer> T.configure(configurer: ExtOf<T>.() -> Any?) = ExtOf.configure(this, configurer)
以上维护有关ThreadLocal
私有变量中最后配置的MarkupContainer
的信息,该变量用于为add
方法的接收器供电.
然后你可以写:
class SomePage() : WebPage() {
init {
configure {
+Label("someLabel", "Some label")
+StatelessForm<Unit>("someForm").configure {
// StatelessForm{} context
+Label("fieldLabel", "Field label")
+RequiredTextField<Long>("someField")
}
}
}
}
正如我上面提到的那样,解决方案虽然有效,但远非漂亮.它可能会令人困惑(因为经常重载的运算符)所以我建议使用常规添加如下:
class SomePage() : WebPage() {
init {
add(
Label("someLabel", "Some label"),
StatelessForm<Unit>("someForm").apply {
// StatelessForm{} context
add(
Label("fieldLabel", "Field label"),
RequiredTextField<Long>("someField")
)
}
}
}
}
我想理想情况下会有一个类似于anko的库,但是对于检票口.