Kotlin function parameter: Val cannot be reassigned

前端 未结 3 1453
一生所求
一生所求 2020-12-03 13:26

I have written Red–black tree in Kotlin. Fun insertFixup restores balance after inserting new element (z: Node? is new element). Algorithm of tree balancin

相关标签:
3条回答
  • 2020-12-03 13:58

    Kotlin function parameters are read-only values and are not assignable.

    You can however create a ReadWriteProperty object to pass to insertFixup for getting/setting newNode:

    ...
    class BinarySearchTree {
    ...
        fun insertFixup(zProperty: ReadWriteProperty<Any?, Node?>) {
            var z by zProperty
    ...
    
    fun main(args: Array<String>) {
        val bst = BinarySearchTree()
    
        var newNode: Node? = null
        val newNodeProperty = object : ReadWriteProperty<Any?, Node?> {
            override operator fun getValue(thisRef: Any?, property: KProperty<*>): Node? {
                return newNode
            }
    
            override operator fun setValue(thisRef: Any?, property: KProperty<*>,
                                           value: Node?) {
                newNode = value
            }
        }
    
        while (true) {
            newNode = Node(readLine()!!.toInt())
            bst.insert(newNode!!)
            bst.insertFixup(newNodeProperty)
        }
    }
    

    And if you are willing to use a property instead of a variable then you can use a property reference for getting/setting newNode from insertFixup instead:

    ...
    class BinarySearchTree {
    ...
        fun insertFixup(zProperty: KMutableProperty0<Node?>) {
            var z by zProperty
    ...
    
    var newNode: Node? = null
    
    fun main(args: Array<String>) {
        val bst = BinarySearchTree()
    
        while (true) {
            newNode = Node(readLine()!!.toInt())
            bst.insert(newNode!!)
            bst.insertFixup(::newNode)
        }
    }
    
    // the following allow `KMutableProperty0` to be used as a read/write delegate
    operator fun <T> KProperty0<T>.getValue(thisRef: Any?, property: KProperty<*>): T = get()
    operator fun <T> KMutableProperty0<T>.setValue(thisRef: Any?, property: KProperty<*>, 
                                                   value: T) = set(value)
    
    0 讨论(0)
  • 2020-12-03 14:11

    I ran into this issue as well. What i did was create a data class and pass the data class as a parameter that i could then use to modify its properties.

    data class SomeDataClass(
        val x: Int,
        val y: Int,
        val z: Int
    )
    
    fun someMethod(someDataClass: SomeDataClass) {
        someDataClass.z = 23 //whatever Int value you please
        // more computations...
        someDataClass.z = 67 // or whatever new value you need to assign.
    }
    
    fun parentMethod() {
        val someDataClass = SomeDataClass()
        someMethod(someDataClass)
        val newZValue = someDataClass.z // someDataClass holds modified data from above 
                                        // method
    }
    
    0 讨论(0)
  • 2020-12-03 14:18

    Function parameters in Kotlin are basically read-only val's inside the function, so z here will always refer to the original object that was passed in.

    If you need to modify what it points to while your function is running, you'll have to make a local copy of it at the beginning of the function, and then you can make that a var.

    For example, you could start your function like this, which lets you reassign this local var later:

    fun insertFixup(_z: Node?) {
        var z = _z
        // ...
        z = z.parent
        // ...
    }
    
    0 讨论(0)
提交回复
热议问题