2

How to have the implementation reference inside a "run" or "apply"

class MyClass : MyCallback {

    ...
    fun myMethod() {
        val myObject = MyObject()
        myObject.run {
            setCallback(this) // <-- How to have the MyCallback's reference here?
        }
    }

    override fun onMyCallback() {
        // Do something
    }
}
2
  • 5
    You can use @ annotation.. for example: this@MyClass Commented Apr 11, 2019 at 13:19
  • Expressions with labels generally increase complexity and worsen the maintainability of the code. It will be blocked by detekt with LabeledExpression error. Commented Apr 11, 2019 at 13:59

2 Answers 2

4

As run is a function that takes a lambda with a receiver (kotlin reference) in the block that is given to run this refers to the receiver, which is in your example myObject.

Therefore you need to use a qualified this-expression to refer to the enclosing MyClass-instance. As stated in the comments you need to change your code like this:

class MyClass : MyCallback {

    ...
    fun myMethod() {
        val myObject = MyObject()
        myObject.run {
            setCallback(this@MyClass) // <-- qualified this
        }
    }

    override fun onMyCallback() {
        // Do something
    }
}

If you want to avoid labels you have to replace the run function. A possible alternative is also which instead of using a lambda with receiver gets the object as parameter:

class MyClass : MyCallback {

    ...
    fun myMethod() {
        val myObject = MyObject()
        myObject.also { obj ->
            //lambda without receiver, this refers to the enclosing instance of MyClass
            setCallback(this)
        }
    }

    override fun onMyCallback() {
        // Do something
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Expressions with labels generally increase complexity and worsen the maintainability of the code. It will be blocked by detekt with LabeledExpression error.
It is still the only way to achieve what you want. The other possibility is to avoid run because it uses a lambda with receiver. A possible alternative is also.
0

recke96 already pointed out two ways to get around that problem, but here is another. Just give this a name outside of the lambda.

class MyClass  {

    fun myMethod() {
        val myObject = MyObject()
        val callback = this // <--
        myObject.run {
            setCallback(callback)
        }
    }
    // ...
}

Or, using let

class MyClass  {

    fun myMethod() {
        val myObject = MyObject()

        let { callback ->
            myObject.run {
                setCallback(callback)
            }
        }
    }
    // ...
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.