Reputation: 521
Could someone explain why can't I change the value of var in that case ?
fun main(args: Array<String>) {
var number = 3
changeNumber(number)
}
fun changeNumber(number: Int) {
number = 4 //here I see a warning "val cannot be reassigned"
}
Upvotes: 1
Views: 1216
Reputation: 93581
Just in case you find the other answers a bit confusing, I'll add that you don't need to know about what's a scalar or passed by value. Those are under-the-hood optimizations that the compiler does but don't change the logical behavior of your code.
Kotlin works only with references, not pointers. What you're trying to do is what you can do with pointers in a language like C or C++. In those languages, you can pass a pointer to a function. A pointer is not the value of a variable, but the memory address of the variable itself so other functions can modify what the variable address is pointing at.
That's flat out not supported in Kotlin. You can only pass references. You are passing the object that the variable is pointing to, but you can't do anything to that variable itself. You are not passing a copy of that object, so if that object is mutable, you could change the values of properties inside it and the original function could see those changes by inspecting the object again. But many simple classes like Int, Float, Double, and String are all immutable, so it's logically irrelevant that you aren't passing a copy (and that's why Kotlin under-the-hood can optimize by passing actual values for some of these, called "inline classes").
A couple of workarounds for this limitation:
data class IntWrapper(var value: Int)
fun main(args: Array<String>) {
val number = IntWrapper(3)
changeNumber(number)
println(number.value)
}
fun changeNumber(number: IntWrapper) {
number.value = 4
}
fun main(args: Array<String>) {
var number = 3
changeNumber { number = it }
println(number)
}
fun changeNumber(numberSetter: (Int)->Unit) {
numberSetter(4)
}
But it's not very often that you'll need to do one of these. It's more common to write functions that provide a return value, and you can use that value to reassign the variable. This strategy is more robust. It provides better encapsulation, which naturally makes your code less bug-prone.
fun main(args: Array<String>) {
var number = 3
number = produceNewNumber()
println(number)
}
fun produceNewNumber(): Int {
return 4
}
Upvotes: 0
Reputation: 131
There is absolutely no way to do it directly. Kotlin copies a value for scalar types (Double, Float, Boolean, Int, etc.). So any internal changes are lost.
For others types Kotlin copy a reference of parameter passed to the function. So any property/field alteration of parameter, also changes the caller parameter.
So you can wrap up your number in for this example an IntegerHolder and change the value that is kept in the reference.
data class IntegerHolder(
var v:Int
)
fun main() {
var a:IntegerHolder = IntegerHolder(2)
changeNumber(a)// Echange a value
print(a.v)
}
fun changeNumber(a:IntegerHolder) {
a.v = 5
}
Upvotes: 3
Reputation: 3015
By passing a "number" to your function you "pass-by-value" NOT "pass-by-reference", the function does not know where in memory your main number is stored, therefore it cannot change it's value
you can see more about the subject here and here
Upvotes: 3