Is it possible to write a “double” extension method?

Is it possible to write a “double” extension method?



In Kotlin, it is possible to write


class A
fun B.foo()



and then e.g. write with (myA) myB.foo() .


with (myA) myB.foo()



Is it possible to write this as an extension method on A, instead? My use case is writing


A


with (java.math.RoundingMode.CEILING) 1 / 2



which I would want to return 1, the point being that I want to add operator fun Int.div(Int) to RoundingMode.


1


operator fun Int.div(Int)


RoundingMode




3 Answers
3



No it's not possible. operator div is required to have Int as a receiver.


operator div


Int



You can't add also RoundingMode as receiver, since there can only be single function receiver.


RoundingMode



What you can do, though, is use Pair<RoundingMode, Int> as a receiver:


Pair<RoundingMode, Int>


operator fun Pair<RoundingMode, Int>.div(i: Int): BigDecimal =
BigDecimal.valueOf(second.toLong()).divide(BigDecimal.valueOf(i.toLong()), first)

with(RoundingMode.CEILING)
println((this to 1) / 2) // => 1






Banged my head on that for half a hour, but this does seem to be the optimal solution.

– Alexey Soshin
Sep 5 '18 at 20:55






My confusion is that it looks like there is a way, in Kotlin, to have two receivers: the class A fun B.foo() example from above, where there are two thises in the method foo. But it doesn't look like there's a way for both of those parameters to be extensions to separate types.

– Louis Wasserman
Sep 5 '18 at 21:32


class A fun B.foo()


this


foo






@LouisWasserman Scala has solution to this - implicits. But Kotlin doesn't.

– Oleksandr.Bezhan
Sep 6 '18 at 13:14






@LouisWasserman Doesn't my answer below (specially the "context class" part) apply to your problem? It's the way I saw JetBrains do some of the Kotlin magic you see with Coroutines lib and Ktor framework

– lucasls
Sep 10 '18 at 20:48




That's not possible, Int already has a div function, thus, if you decide to write an extension function div, you won't be able to apply it, because member functions win over extension functions.


Int


div


div



You can write this though:


fun RoundingMode.div(x: Int, y: Int): Int
return if (this == RoundingMode.CEILING)
Math.ceil(x.toDouble() / y.toDouble()).toInt()
else
Math.floor(x.toDouble() / y.toDouble()).toInt()



fun main(args: Array<String>)
with(java.math.RoundingMode.CEILING)
println(div(1,2))




It's not possible for a couple of reasons:


div


Int



However you can workaround these issues with


block: ContextClass.() -> Unit


15 div 4


15 / 4



See the example below:


class RoundingContext(private val roundingMode: RoundingMode)
infix fun Int.div(b: Int): Int
val x = this.toBigDecimal()
val y = b.toBigDecimal()

val res = x.divide(y, roundingMode)

return res.toInt()



fun <T> using(roundingMode: RoundingMode, block: RoundingContext.() -> T): T
return with(RoundingContext(roundingMode))
block()



// Test
fun main(args: Array<String>)
using(RoundingMode.FLOOR)
println(5 div 2) // 2

val x = using(RoundingMode.CEILING)
10 div 3

println(x) // 4



Hope it helps!



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)