Kotlin函数参数:Val不能重新分配

时间:2017-03-01 19:09:41

标签: pointers kotlin var

我在Kotlin写过红黑树。 Fun insertFixup 在插入新元素后恢复平衡( z:Node?是新元素)。树平衡算法取自here(第2-3页)。 问题是Kotlin 不允许我将 z 重新分配给 z.parent z。 parent.parent 。我希望 z 成为指针。问题是如何让Kotlin明白我对他的要求?

class Node(key: Int) {...}

class BinarySearchTree {
    var root: Node? = null

    fun insert(newNode: Node) {...}

    fun RotateLeft(x: Node?) {...}

    fun RotateRight(x: Node?) {...}

    fun insertFixup(z: Node?) {
        var y: Node?
        while (z?.parent?.color == "RED") {
            if (z?.parent == z?.parent?.parent?.left) {
                y = z?.parent?.parent?.right
                if (y?.color == "RED") {
                    z?.parent?.color = "BLACK"
                    y?.color = "BLACK"
                    z?.parent?.parent?.color = "RED"
                    z = z?.parent?.parent
                }
                if (z == z?.parent?.right) {
                    z = z?.parent
                    RotateLeft(z)
                    z?.parent?.color = "BLACK"
                    z?.parent?.parent?.color = "RED"
                    RotateRight(z?.parent?.parent)
                }
            } else {
                y = z?.parent?.parent?.left
                if (y?.color == "RED") {
                    z?.parent?.color = "BLACK"
                    y?.color = "BLACK"
                    z?.parent?.parent?.color = "RED"
                    z = z?.parent?.parent
                }
                if (z != z?.parent?.left) {
                    z = z?.parent
                    RotateLeft(z)
                    z?.parent?.color = "BLACK"
                    z?.parent?.parent?.color = "RED"
                    RotateRight(z?.parent?.parent)
                }
            }
        }
        root?.color = "BLACK"
    }
}

fun main(args: Array<String>) {
    val bst = BinarySearchTree()

    while (true) {
        var newNode = Node(readLine()!!.toInt())
        bst.insert(newNode)
        bst.insertFixup(newNode)
    }
}

UPD:感谢大家!所有的答案都很有帮助,我在你的回复中找到了解决方案。

4 个答案:

答案 0 :(得分:15)

Kotlin中的函数参数在函数内部是只读的val,因此这里的z将始终引用传入的原始对象。

如果您需要修改功能运行时指向的内容,您必须在功能开头制作本地副本,然后才能将其设为var

例如,你可以像这样开始你的功能:

fun insertFixup(_z: Node?) {
    var z = _z

答案 1 :(得分:5)

Kotlin函数参数是只读值,不可分配。

但是,您可以创建ReadWriteProperty对象以传递给insertFixup以获取/设置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)
    }
}

如果您愿意使用属性而不是变量,那么您可以使用property referencenewNode获取/设置insertFixup

...
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)

答案 2 :(得分:1)

我也遇到了这个问题。我所做的就是创建一个数据类,并将该数据类作为参数传递给我,然后可以使用它来修改其属性。

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
}

答案 3 :(得分:0)

就我而言,我正在研究管理不同应用程序数据的内容提供程序。我得到了一个新的 kotlin 文件,它从 Content Provider 继承属性,如下所示:

class ProviderClass() : ContentProvider(){

}

ContentProvider() 是一个抽象类,所以我们需要实现所有的成员。

我试图将值重新分配给 sortOrder 参数,在那个参数上我遇到了这些问题。 我所做的解决的是, //实现成员后

....
override fun query(
        uri: Uri,
        projection: Array<out String>?,
        selection: String?,
        selectionArgs: Array<out String>?,
        sortOrder: String?
    ): Cursor? {
var _sortOrder = sortOrder
if (sortOrder == null || sortOrder == ""){
            _sortOrder = NAME
        }
val cursor = qb.query(db, projection, selection, selectionArgs, null, null, _sortOrder) //_sorOrder newly created variable

我创建了一个名为 _sortOrder 的新变量,并将该新创建的变量放在第二个空值之后的查询方法上,在那里我创建了一个名为 cursor 的新变量,并将我们新创建的变量设置为我们想要设置的值