Home > OS >  Kotlin - Companion Object with Receiver Function
Kotlin - Companion Object with Receiver Function

Time:06-25

I guess it's an outright "NO", but here is my class

class KotlinReceiverFunction {

    val multiplyBy = fun Int.(value: Int) = this*value

    companion object {
        fun printMultiplicationResult(a: Int, b: Int) = a.multiplyBy(b) // error
    }
}

My question - is Receiver Function only allowed within a specific scope i.e. same as Lambdas? Or, can I get to work somehow in a companion object?

Regards

CodePudding user response:

There are no restrictions on where a function with a receiver could be used. The problem in your case is different: multiplyBy is an instance member, so you need an instance of KotlinReceiverFunction to use it. It would be exactly the same if this function would not use a receiver:

val multiplyBy = fun (value1: Int, value2: Int) = value1*value2

companion object {
    fun printMultiplicationResult(a: Int, b: Int) = multiplyBy(a, b) // error
}

To fix the problem you need to initialize an instance of KotlinReceiverFunction:

fun printMultiplicationResult(a: Int, b: Int) =
    with(KotlinReceiverFunction()) { a.multiplyBy(b) } // works

Although, I think this is not exactly what you need.

CodePudding user response:

This has nothing to do with receivers. You are using the correct receiver. It's just that things declared outside the companion object is out of scope inside the companion object:

class KotlinReceiverFunction {
    val foo = 1
    companion object {
        fun bar() {
            println(foo) // error
        }
    }
}

Think of KotlinReceiverFunction and its companion object as two disconnected things. Under the hood on the JVM, they are just two separate classes KotlinReceiverFunction and KotlinReceiverFunction$Companion, each with their own instance members.

In the companion object, You would need an instance of KotlinReceiverFunction to access its foo property. This instance acts as the receiver.

companion object {
    fun bar() {
        println(KotlinReceiverFunction().foo) // OK
    }
}

Similarly, the multiplyBy function needs an instance of KotlinReceiverFunction as its receiver (dispatch receiver). But this function also needs an Int as a receiver (extension receiver)!

This makes it a little harder to access than foo when you are in the companion object. You would need to provide the instance of KotlinReceiverFunction with a scope function, as in broot's answer.


If you just declare the function inside the companion object, then it will work as you expect:

class KotlinReceiverFunction {
    companion object {

        val multiplyBy = fun Int.(value: Int) = this*value
        fun printMultiplicationResult(a: Int, b: Int) = a.multiplyBy(b)
    }
}

I don't see a reason why this needs to be a val initialised with an anonymous function. You could have just done:

private fun Int.multiplyBy(value: Int) = this * value
  • Related