如何在不可变的Kotlin类中创建父子关系
我有表示树的不可变类,其中子级需要父级引用如何在不可变的Kotlin类中创建父子关系,kotlin,Kotlin,我有表示树的不可变类,其中子级需要父级引用 sealed class Node { abstract val parent: Parent? } class Child( override val parent: Parent, ) : Node() class Parent( override val parent: Parent?, val children: List<Node> ) : Node() sealed class Node {
sealed class Node {
abstract val parent: Parent?
}
class Child(
override val parent: Parent,
) : Node()
class Parent(
override val parent: Parent?,
val children: List<Node>
) : Node()
sealed class Node {
abstract val parent: Parent?
}
class Child(
override val parent: Parent
) : Node()
class Parent(
override val parent: Parent?,
val children: List<Node>
) : Node() {
companion object {
operator fun invoke(parent: Parent?, childBuilders: List<(Parent) -> Node>): Parent {
val children = mutableListOf<Node>()
return Parent(parent, children).apply {
children.addAll(childBuilders.map { it(this) })
}
}
}
}
密封类节点{
抽象val父:父?
}
班童(
覆盖val父项:父项,
):Node()
班级家长(
覆盖val父项:父项?,
val子项:列表
):Node()
是否有一种惯用的Kotlin方法来创建一个包含正确设置了父引用的子项列表的父项?另一种方法是从
节点中设置父项
,并为其提供一个要设置父项的子项列表
sealed class Node(
children: List<Node> = listOf()
) {
var parent: Container? = null
private set
init {
(this as? Container)?.apply {
children.forEach { it.parent = this }
}
}
}
data class Child(val type: String) : Node()
data class Container(
val children: List<Node>
) : Node(children)
密封类节点(
子项:List=listOf()
) {
变量父级:容器?=null
专用设备
初始化{
(此为?容器)?。应用{
children.forEach{it.parent=this}
}
}
}
数据类子级(val类型:String):节点()
数据类容器(
val子项:列表
):节点(子节点)
唯一的副作用是,父级
不会被数据类用作属性。另一种方法是,使父级
在节点
内可设置,并为其提供子级列表以设置父级
sealed class Node(
children: List<Node> = listOf()
) {
var parent: Container? = null
private set
init {
(this as? Container)?.apply {
children.forEach { it.parent = this }
}
}
}
data class Child(val type: String) : Node()
data class Container(
val children: List<Node>
) : Node(children)
密封类节点(
子项:List=listOf()
) {
变量父级:容器?=null
专用设备
初始化{
(此为?容器)?。应用{
children.forEach{it.parent=this}
}
}
}
数据类子级(val类型:String):节点()
数据类容器(
val子项:列表
):节点(子节点)
唯一的副作用是,
parent
不会被数据类用作属性。与其坚持不可变,不如选择只读。可以将其视为类似于kotlinsMutableList
/List
。大概是这样的:
sealed class Node {
abstract val parent: Container?
}
abstract class Child : Node()
abstract class Container : Node() {
abstract val children: List<Node>
}
private class MutableChild(override var parent: Container?) : Child()
private class MutableContainer(override var parent: Container?, override var children: List<Node>) : Container()
fun buildTree() : Node {
val children = mutableListOf<Node>()
val parent = MutableContainer(null, children)
MutableChild(parent).also { children.add(it) }
MutableChild(parent).also { children.add(it) }
return parent
}
密封类节点{
摘要:容器?
}
抽象类子节点:Node()
抽象类容器:节点(){
抽象val子项:列表
}
私有类MutableChild(重写变量parent:Container?:Child()
私有类MutableContainer(覆盖变量父级:Container?,覆盖变量子级:List):Container()
fun buildTree():节点{
val children=mutableListOf()
val parent=MutableContainer(null,子项)
MutableChild(parent).allow{children.add(it)}
MutableChild(parent).allow{children.add(it)}
返回父级
}
与其坚持不变性,不如选择只读。可以将其视为类似于kotlinsMutableList
/List
。大概是这样的:
sealed class Node {
abstract val parent: Container?
}
abstract class Child : Node()
abstract class Container : Node() {
abstract val children: List<Node>
}
private class MutableChild(override var parent: Container?) : Child()
private class MutableContainer(override var parent: Container?, override var children: List<Node>) : Container()
fun buildTree() : Node {
val children = mutableListOf<Node>()
val parent = MutableContainer(null, children)
MutableChild(parent).also { children.add(it) }
MutableChild(parent).also { children.add(it) }
return parent
}
密封类节点{
摘要:容器?
}
抽象类子节点:Node()
抽象类容器:节点(){
抽象val子项:列表
}
私有类MutableChild(重写变量parent:Container?:Child()
私有类MutableContainer(覆盖变量父级:Container?,覆盖变量子级:List):Container()
fun buildTree():节点{
val children=mutableListOf()
val parent=MutableContainer(null,子项)
MutableChild(parent).allow{children.add(it)}
MutableChild(parent).allow{children.add(it)}
返回父级
}
我们可以在第一次需要孩子的时候懒洋洋地评估一个构建者列表。注意,只有当代码库的其余部分足够透明时,这才是安全的
sealed class Node {
abstract val parent: Parent?
}
class Child(
override val parent: Parent
) : Node()
class Parent(
override val parent: Parent?,
private val childBuilders: List<(Parent) -> Node>
) : Node() {
val children: List<Node> by lazy {
childBuilders.map { it(this)}
}
}
密封类节点{
抽象val父:父?
}
班童(
覆盖val父项:父项
):Node()
班级家长(
覆盖val父项:父项?,
private val childBuilders:列表节点>
):Node(){
val儿童:按懒惰列出{
childBuilders.map{it(this)}
}
}
我们可以在第一次需要孩子的时候懒洋洋地评估一个构建者列表。注意,只有当代码库的其余部分足够透明时,这才是安全的
sealed class Node {
abstract val parent: Parent?
}
class Child(
override val parent: Parent
) : Node()
class Parent(
override val parent: Parent?,
private val childBuilders: List<(Parent) -> Node>
) : Node() {
val children: List<Node> by lazy {
childBuilders.map { it(this)}
}
}
密封类节点{
抽象val父:父?
}
班童(
覆盖val父项:父项
):Node()
班级家长(
覆盖val父项:父项?,
private val childBuilders:列表节点>
):Node(){
val儿童:按懒惰列出{
childBuilders.map{it(this)}
}
}
您可以尝试使用根节点和生成器参数:
sealed class Node {
data class Root(
val createChildren: ParentList.() -> Unit
) : Node() {
val children: List<Node> = ParentList(this).apply(createChildren)
}
data class Branch(
val createChildren: ParentList.() -> Unit,
val parent: Node
) : Node() {
val children: List<Node> = ParentList(this).apply(createChildren)
}
data class Leaf(
val parent: Node
) : Node()
}
class ParentList(
val parent: Node,
private val children: MutableList<Node> = mutableListOf()
) : List<Node> by children {
fun branch(createChildren: ParentList.() -> Unit) {
children += Node.Branch(createChildren, parent)
}
fun leaf() {
children += Node.Leaf(parent)
}
}
fun root(createChildren: ParentList.() -> Unit) = Node.Root(createChildren)
您可以允许访问具有扩展属性的潜在子级和/或父级:
val Node.children: List<Node> get() = when(this) {
is Node.Root -> children
is Node.Branch -> children
is Node.Leaf -> emptyList()
}
val Node.parent: Node? get() = when(this) {
is Node.Root -> null
is Node.Branch -> parent
is Node.Leaf -> parent
}
val Node.children:List get()=何时(此){
是Node.Root->children
是Node.Branch->children
是Node.Leaf->emptyList()
}
val Node.parent:节点?get()=当(此){
是Node.Root->null
是Node.Branch->parent
是Node.Leaf->parent
}
因此,您可以导航子体:
fun Node.allChildren(): List<Node> =
children + children.flatMap { it.allChildren() }
fun Node.allChildren():列表=
children+children.flatMap{it.allChildren()}
或向上导航:
fun Node.allParents(): List<Node> =
listOfNotNull(parent).flatMap { listOf(it) + allParents() }
fun节点。allParents():列表=
listOfNotNull(父).flatMap{listOf(it)+allParents()}
要避免在执行可能提前完成的搜索时进行评估,您可以始终使用序列而不是列表:
fun Node.allChildren(): Sequence<Node> =
children.asSequence() + children.asSequence().flatMap { it.allChildren() }
fun Node.allParents(): Sequence<Node> =
listOfNotNull(parent).asSequence().flatMap { sequenceOf(it) + it.allParents() }
fun Node.allChildren():序列=
children.asSequence()+children.asSequence().flatMap{it.allChildren()}
有趣的节点。allParents():序列=
listOfNotNull(parent.asSequence().flatMap{sequenceOf(it)+it.allParents()}
注意:注意堆栈溢出您可以尝试使用根节点和生成器参数:
sealed class Node {
data class Root(
val createChildren: ParentList.() -> Unit
) : Node() {
val children: List<Node> = ParentList(this).apply(createChildren)
}
data class Branch(
val createChildren: ParentList.() -> Unit,
val parent: Node
) : Node() {
val children: List<Node> = ParentList(this).apply(createChildren)
}
data class Leaf(
val parent: Node
) : Node()
}
class ParentList(
val parent: Node,
private val children: MutableList<Node> = mutableListOf()
) : List<Node> by children {
fun branch(createChildren: ParentList.() -> Unit) {
children += Node.Branch(createChildren, parent)
}
fun leaf() {
children += Node.Leaf(parent)
}
}
fun root(createChildren: ParentList.() -> Unit) = Node.Root(createChildren)
您可以允许访问具有扩展属性的潜在子级和/或父级:
val Node.children: List<Node> get() = when(this) {
is Node.Root -> children
is Node.Branch -> children
is Node.Leaf -> emptyList()
}
val Node.parent: Node? get() = when(this) {
is Node.Root -> null
is Node.Branch -> parent
is Node.Leaf -> parent
}
val Node.children:List get()=何时(此){
是Node.Root->children
是Node.Branch->children
是Node.Leaf->emptyList()
}
val Node.parent:节点?get()=当(此){
是Node.Root->null
是Node.Branch->parent
是Node.Leaf->parent
}
因此,您可以导航子体:
fun Node.allChildren(): List<Node> =
children + children.flatMap { it.allChildren() }
fun Node.allChildren():列表=
children+children.flatMap{it.allChildren()}
或