【发布时间】:2020-11-13 16:21:09
【问题描述】:
这个问题涉及静态类型语言中的设计模式,尤其是动态绑定(我在这里使用 Kotlin,但也可以是 C++ 或 Java)。问题如下:我有一个接口Node(代表Ast中的节点)和多个元素的串联(有多个这样的类)。
interface Node {
fun concat(next: Node): Node {
return Concat(listOf(this, next))
}
}
class Concat(val nodes: List<Node>): Node {
}
我现在想确保 Concat 始终是扁平的,即没有一个节点是串联的。使用if(next is Concat) 类型检查会很容易,但我想使用动态绑定并避免此类类型检查。我的第一次失败的解决方案尝试如下:
interface Node {
fun concat(next: Node): Node {
return next.reverseConcat(this)
}
fun reverseConcat(prev: Node): Node {
return Concat(prev, this)
}
}
class Concat(val nodes: List<Node>): Node {
override fun concat(next: Node): Node {
// TODO what if next is a Concat?
return Concat(nodes + next)
}
override fun reverseConcat(prev: Node): Node {
// TODO what if prev is a Concat?
return Concat(listOf(prev) + nodes)
}
}
但是如果两个节点都是 Concat 的实例,这将失败。另一种解决方案尝试是添加reverseConcat-methods 和Concat 作为参数。
interface Node {
// ...
fun reverseConcatWithConcat(nextNodes: List<Node>): Node {
return Concat(listOf(this) + nextNodes)
}
}
class Concat(val nodes: List<Node>): Node {
override fun concat(next: Node): Node {
return next.reverseConcatWithConcat(nodes)
}
override fun reverseConcat(prev: Node): Node {
// TODO what if prev is a Concat?
return Concat(listOf(prev) + nodes)
}
fun reverseConcatWithConcat(nextNodes: List<Node>): Node {
return Concat(nodes + nextNodes)
}
}
这会起作用,但它会使接口变得混乱(考虑到还有其他节点,类似于 Concat),并且它还留下了接口中没有受保护的方法的问题,因此 reverseConcat 仍然很危险。
有没有更令人满意的方法使用动态绑定,不会不必要地混乱代码?
【问题讨论】:
标签: oop kotlin design-patterns polymorphism dynamic-binding