Extension Function/Property with two receivers

I think it would be a nice addition if we could write Extensions Properties (and Functions) with two Receivers.
It would allow us to define extension Functions which are only valid in a specific content, for example in an Android Activity / Context.

Example:

val Context.Int.dip: Int 
    get() = (value * this@Context.resources.displayMetrics.density).toInt()

instead of

fun Context.dip(value: Int): Int = (value * resources.displayMetrics.density).toInt()

So the usage would be:

width = 8.dip

instead of

width = dip(8)

Of course in this scenario it is only a small improvement, but in my opinion this addition could be useful in many situations.
What do you think?

6 Likes

Totally agreed !

We’ve seen several usecases where such properties could be needed, but so far we’re trying to avoid adding them to the language. Single-receiver extension properties can be hard enough to explain, and this becomes even less obvious.

Note that your scenario can be partially solved with a member extension property defined in a base class that all of your activities extend.

1 Like

Is it possible to define member-extension with multiple receivers outside of the class, like this:

/* File 1: */
class A {
}

class B {
}


/* File 2: */
reopen class A {
     fun B.extension() {
     }
}

fun something() {
    /* here I want to use an extension on A, B */
}

/*or*/
fun A.extension1() {
    val x = fun B.extension2() {
    }
}

No, member extension functions can’t be defined outside of a class.

Thank you for your response!

I know that my scenario could be resolved with a member extension property defined in a base class, but there are many scenarios where this approach doesn’t work.
Also such methods would be very useful for creating DSLs for existing frameworks (see Anko’s _LinearLayout.lparams() method).

While I understand the argument, that such methods could be sometimes hard to understand, I still hope that you will change your point of view regarding this topic some day :slight_smile:

1 Like

I am developping a Computer Algebra System in Kotlin (on top of MetaMaths) and I would really like to be able to define 2 receiver extension functions outside of a class (because, at one point the class will be much too big and it will break)

Ther are like a gazillion methods that takes a math Statement and a math Context that scream to return a math Statement and it is not possible for me to work around maths.

Single receiver extension functions have proved to be one major feature of Kotlin. Maybee 2 receiver extension functions could have the same fate.

“Avoiding a feature in a language because it is hard to explain, though you have seen several > usecases” and it is already implemented and publicly used but you have to work around arbitrary > restrictions by defining what you want in a single class

does not sound to me like a valid reason not to introduce 2 receiver extension functions


Take a look at

2 Likes

Wow, Many thanks for that link. I’m interested. Like a lot.