在Kotlin中通过引用传递整数

时间:2018-08-01 17:14:04

标签: kotlin

我正在尝试创建一个交换函数,该函数需要两个参数,如下所示:

fun swap(a :Int, b:Int) {

}

我这样称呼它:

  var a = 10
    var b = 5

    swap(a,b)

    // a should be 5
    // b should be 10

问题在于,即使我在交换函数中交换值,也不会反映在调用方,因为它是作为副本而不是作为引用传递的。

无论如何,是否有将值类型传递给交换函数并允许函数更改它们的能力。

4 个答案:

答案 0 :(得分:1)

我知道OP并没有要求这样做,但是idiomatic Kotlin看起来像这样:

var a = 1
var b = 2
a = b.also { b = a }

答案 1 :(得分:0)

看起来像Kotlin的行为非常类似于Java: Is Kotlin "pass-by-value" or "pass-by-reference"?

交换的简单方法是设置支持类


private fun swap(pair: Pair) {
    pair.a += pair.b
    pair.b = pair.a - pair.b
    pair.a = pair.a - pair.b
}

private data class Pair(var a: Int, var b: Int)

fun main() {

    val pair = Pair(10, 5)
    swap(pair)
    println(pair)

}

答案 2 :(得分:0)

绝对没有办法直接做到这一点。 Kotlin 复制标量类型(DoubleFloatBooleanInt等的值)。因此,所有内部更改都将丢失。

对于任何其他类型,Kotlin复制传递给该函数的参数的引用。因此,参数的任何属性/字段更改都会更改调用方参数。

无法更改此行为。

尝试了许多方法以克服通过引用传递标量的可能性,例如 Kotlin Java 和其他一些语言;正如上面的注释所建议的那样,我目前的策略是对任何标量类型使用普通的和通用的包装。

最近,我对所有东西都使用了这个技巧,包括在一个函数内部,否则该函数将要求我返回多个值。另一种方法是将返回值加入人工类或解构声明中:val (a, b, c) = function-call()语法。但是,我讨厌关节类,并且解构声明仅适用于局部变量,当某些组件需要当前命令块之外的可见性时,这很烦人。

我的代码很简单:

data class p<T>(   // It's a generic wrap class for scalar type T
   var v:T
)

fun <T>swap(a:p<T>, b:p<T>){  // It's a generic swap for scalar types
  var aux:p<T> = a.copy()
  a.v = b.v
  b.v =aux.v 
}


fun main() {
  var a:p<Int> = p<Int>(2)   // 'a' is a kind of 'Int' variable
  var b:p<Int> = p<Int>(3)   // and so is 'b'
  swap(a,b)  // Exchange 'a' and 'b' values
  println(a.v)  // 3
  println(b.v)  // 2
}

唯一的缺点是无法使用实标量类型的语法糖。
我必须在使用标量变量时添加.v

我仅将其用于需要在某些函数中通过引用传递的变量,这种情况并不常见。我会尽可能避免附带影响。

答案 3 :(得分:0)

您可以拥有一个获取变量引用的函数

var x = 10
var y = 20

fun main() {
    println("x=$x, y=$y") // x=10, y=20
    swap(::x, ::y)
    println("x=$x, y=$y") // x=20, y=10
}

fun <T> swap(firstRef: KMutableProperty0<T>, secRef: KMutableProperty0<T>) {
    val temp = firstRef.get()
    firstRef.set(secRef.get())
    secRef.set(temp)
}

,您可以传递类似swap(someClass::x, someClass::y)

这样的类的属性的引用

唯一的限制是您不能传递不是世界末日的局部变量的引用。

如果您不喜欢凌乱的语法,则可以随时定义一个typealias并使其美观:

typealias Ref<T> =  KMutableProperty0<T>

fun <T> swap(firstRef: Ref<T>, secRef: Ref<T>) {
    ...
}