Kotlin 函数参数:Val 不能被重新赋值
Kotlin function parameter: Val cannot be reassigned
我用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: 谢谢大家!所有的答案都很有帮助,我在你的回复中找到了解决方案。
Kotlin 中的函数参数基本上是只读的 val
在函数内部,所以这里 z
将始终引用传入的原始对象。
如果您需要修改它指向的内容,而您的函数是 运行,您必须在函数的开头创建它的本地副本,然后您可以将其设为 var
.
例如,您可以像这样启动您的函数,这样您就可以稍后重新分配此本地 var
:
fun insertFixup(_z: Node?) {
var z = _z
// ...
z = z.parent
// ...
}
Kotlin 函数参数是只读值,不可赋值。
但是您可以创建一个 ReadWriteProperty
对象传递给 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)
}
}
如果您愿意使用 属性 而不是变量,那么您可以使用 property reference for getting/setting newNode
from 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)
我也运行关注这个问题。我所做的是创建一个数据 class 并将数据 class 作为参数传递,然后我可以使用它来修改其属性。
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
}
就我而言,我正在研究管理不同应用程序数据的内容提供者。我得到了一个新的 kotlin 文件,它继承了 Content Provider 的属性,如下所示:
class ProviderClass() : ContentProvider(){
}
ContentProvider()
是一个抽象class,所以我们需要实现所有的成员。
我试图将值重新分配给 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 的新变量,并将新创建的变量设置为我们想要的值设置它。
我用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: 谢谢大家!所有的答案都很有帮助,我在你的回复中找到了解决方案。
Kotlin 中的函数参数基本上是只读的 val
在函数内部,所以这里 z
将始终引用传入的原始对象。
如果您需要修改它指向的内容,而您的函数是 运行,您必须在函数的开头创建它的本地副本,然后您可以将其设为 var
.
例如,您可以像这样启动您的函数,这样您就可以稍后重新分配此本地 var
:
fun insertFixup(_z: Node?) {
var z = _z
// ...
z = z.parent
// ...
}
Kotlin 函数参数是只读值,不可赋值。
但是您可以创建一个 ReadWriteProperty
对象传递给 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)
}
}
如果您愿意使用 属性 而不是变量,那么您可以使用 property reference for getting/setting newNode
from 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)
我也运行关注这个问题。我所做的是创建一个数据 class 并将数据 class 作为参数传递,然后我可以使用它来修改其属性。
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
}
就我而言,我正在研究管理不同应用程序数据的内容提供者。我得到了一个新的 kotlin 文件,它继承了 Content Provider 的属性,如下所示:
class ProviderClass() : ContentProvider(){
}
ContentProvider()
是一个抽象class,所以我们需要实现所有的成员。
我试图将值重新分配给 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 的新变量,并将新创建的变量设置为我们想要的值设置它。