Search code examples
kotlinkotlin-extension

How to create variables on parent context


I'm trying to implement something similar to this syntax in Kotlin

class MyClass() {
    fun before(init: () -> Unit): Unit {
        with(this) init
    }
    fun after(block: () -> Unit): Unit {
        with(this) block
    }
}

fun main () {
    var myClass = MyClass()
    myClass.before {
        var a = 5
    }
    myClass.after {
        println("Double of a is ${a * 2}")
    }
}

Right now this won't work because a cannot be resolved within after. I understand that this is due to the way the closures work.

My question is if there is some mechanism in Kotlin that would allow me to do this, create variables in a closure/extension in such a way that they would be stored in the receiver object and be accessible to other closures/extensions.

This is part of an effort to migrate a Groovy script to Kotlin.

Disclaimer: This is my very first go at Kotlin. I've read through the docs but I may be missing something (a lot). Feel free to just point at the right direction

EDIT: Adding compilable example

class Aa() {

    var a: Int = 0
    var bb: () -> Unit = null!!

    fun ww (block: () -> Unit) {
        bb = block
    }

    fun doit(block: () -> Unit) {
        with(bb) {
            block()
        }
    }

}

fun main(args: Array<String>) {
    val exec = fun Aa.(other: () -> Unit): Unit = other()

    aa.ww {
        var xx = 5
    }

    aa.doit {
        // println("with $xx") <- this fails
    }
}

Solution

  • Kotlin is a statically typed language. It's not possible to store data inside the instance of an object for which there is no field inside that object.

    You could define a property of type Map, and store the values inside that map, but you won't be able to access them using the regular property syntax unless you know in advance which values will be stored there.