Kotlin-将“this”作为构造函数参数传递

disho6za  于 2023-10-23  发布在  Kotlin
关注(0)|答案(1)|浏览(131)

我在写一个二叉树类。我想避免null值,我决定使用指定值nil。所以,当一个元素没有左子元素时,我有n.left = nil而不是n.left = null。但是,我需要为nil指定左子节点和右子节点,唯一的选择是nil本身。所以,我想这样写:

class Node(val left: Node, val right: Node) {
    companion object {
        val nil = Node(nil, nil)
    }
}

或至多:

class Node(val left: Node, val right: Node) {
    private constructor(): this(this, this)
    companion object {
        val nil = Node()
    }
}

当然,这些都不能编译。这是我被迫写的:

class Node {
    val left: Node
    val right: Node
    constructor(left: Node, right: Node) {
        this.left = left
        this.right = right
    }
    private constructor() {
        this.left = this
        this.right = this
    }
    companion object {
        val nil = Node()
    }
}

它有更多的代码,特别是在我添加了更多的字段之后。有什么方法可以写得简洁一点吗?

9udxz4iz

9udxz4iz1#

  • 免责声明:**我会重新考虑你的回避无效。可空性内置于Kotlin的类型系统中,null是“无值”的一个很好的表示。另外,Kotlin有safe call(?.)和elvis(?:)操作符,并有智能转换,可以检查null。

如果你想避免可空类型,那么也许像这样的东西对你有用:

sealed interface Node {
    val left: Node
    val right: Node
}

object EmptyNode : Node {
    override val left: EmptyNode get() = this
    override val right: EmptyNode get() = this
}

class RegularNode(
    override val left: Node = EmptyNode,
    override val right: Node = EmptyNode,
) : Node

但是它需要您为添加到Node接口的每个属性和函数更新两个实现。如果可能的话,你可以使用扩展函数。
也就是说,我假设您将向Node添加value属性。考虑到您的用例的性质,这个属性必须是通用的。这使得事情变得更加困难,尽管你可以尝试这样的事情:

val Node<*>.isEmptyNode: Boolean
    get() = this is EmptyNode<*>

sealed interface Node<T> {
    val left: Node<T>
    val right: Node<T>
    val value: T
}

class EmptyNode<T> : Node<T> {
    override val left: EmptyNode<T> get() = this
    override val right: EmptyNode<T> get() = this
    override val value: Nothing
        get() = throw IllegalStateException("EmptyNode has no value")
}

class RegularNode<T>(
    override val value: T,
    override val left: Node<T> = EmptyNode(),
    override val right: Node<T> = EmptyNode(),
) : Node<T>

但是注意现在EmptyNode不是单例。

相关问题