iadcialim24
iadcialim24

Reputation: 4015

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

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.

Upvotes: 4

Views: 10572

Answers (2)

RobCo
RobCo

Reputation: 6495

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

    }
}

Upvotes: 3

guenhter
guenhter

Reputation: 12167

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
        }

    }
}

Upvotes: 1

Related Questions