Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: Pass object in function as reference and change its instance

Tags:

android

kotlin

I cannot find how to pass the reference of the objects so that I can let them point to a new location in the memory. How to do this in Kotlin?

Code:

class Parent {

}

class Child : Parent {

}

class GlobalDataHolder {

    var globalChildVriable: Child? = null // imagine this is a static variable and can be accessed anywhere
}

class Activity() {
    var variable1 = Child()

    Helper.init(variable1, GlobalDataHolder.globalChildVriable) // inside onCreate()

}

class Helper {

    initStuff(variable1: Parent, globalVariable: Parent?) {
        if (globalVariable == null) {
             globalVariable = variable1 // error saying val cannot be re-assigned
        }
        else {
            variable1 = globalVariable!!
        }

    }
}

I want variable1 and globalVariable to be modifiable. So the original owners of them will have the latest values.

like image 511
iori24 Avatar asked Nov 08 '25 10:11

iori24


2 Answers

Kotlin (and Java) do not natively support reference types like C/C++ do. However, kotlin does have property and functional types.
A property is basically just a combination of 2 functions (a getter and a setter). You can pass properties as arguments and, with reflection, call their getter setter individually from a different context.

Updated (compilable) code:

open class Parent { }

open class Child : Parent() { }


var globalVariable: Child? = null


class Activity() {

    var localVariable = Child()

    init {
        Helper.initStuff(this::localVariable, ::globalVariable)
    }

}

object Helper {

    fun initStuff(localProperty: KMutableProperty0<out Parent>, globalProperty: KMutableProperty0<out Parent?>) {
        val globalVariable = globalProperty.call()
        val variable1 = localProperty.call()

        if (globalVariable == null) {
            globalProperty.setter.call(variable1)
        }
        else {
            variableProperty.setter.call(globalVariable)
        }

    }
}
like image 156
RobCo Avatar answered Nov 10 '25 01:11

RobCo


Such problems can "always" be solved by introducing one more level of abstraction. You can for example add a new interface VarHolder which is responsible for getting/setting the contained variable.

interface VarHandle<E> {
    var variable: E
}
class Activity() {
    var variable1 = Child()

    fun onCreate() {
        Helper.initStuff(object : VarHandle<Child> {
            override var variable: Child
                get() = variable1
                set(value) { variable1 = value }

        }, object : VarHandle<Child?> {
            override var variable: Child?
                get() = GlobalDataHolder.globalChildVariable
                set(value) { GlobalDataHolder.globalChildVariable = value }
        })
    }
}

object Helper {

    fun initStuff(localVarHolder: VarHandle<Child>, globalVarHolder: VarHandle<Child?>) {
        val globalVar = globalVarHolder.variable
        val localVar = localVarHolder.variable

        if (globalVar == null) {
            globalVarHolder.variable = localVar
        }
        else {
            localVarHolder.variable = globalVar
        }

    }
}
like image 45
guenhter Avatar answered Nov 10 '25 03:11

guenhter



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!