Extension Functions of Same Name with Different Receiver


#1

Should it be possible to create an extension function of the same name against 2 different receiver types (within the same namespace)?

The reason I ask is that I keep getting this error…

  java.lang.ClassFormatError: Duplicate method name&signature in class file expectations/namespace


#2

Or better yet how would I achieve some like this,

fun Double.isInRange(val lower: Double, val upper: Double) {
  return this >= lower && this <= upper
}

fun Float.isInRange(val lower: Double, val upper: Double) {   return this >= lower && this <= upper }

fun Int.isInRange(val lower: Double, val upper: Double) {   return this >= lower && this <= upper }

fun Long.isInRange(val lower: Double, val upper: Double) {   return this >= lower && this <= upper }

I looked at using Number as the base class but I dont quite grasp how covariance works in generics in Kotlin (also Number itself isn’t comperable so I was casting everything to a Double - this.toDouble() which doesn’t seem to sit right with me.)


#3

Kotlin Compiler version 0.1.2580 Last IDEA plugin, work pretty normal.

package runs

fun main(args: Array<String>) {
  println(4.toLong().isInRange(1.0, 10.0))
  println(16.0.isInRange(1.0, 10.0))

  println(8.toLong() in 1…16.toLong())
}

fun Double.isInRange(val lower: Double, val upper: Double): Boolean {
  return this >= lower && this <= upper
}

fun Long.isInRange(val lower: Double, val upper: Double): Boolean {
  return this >= lower && this <= upper
}


Look at ‘in’ statement, you can override it http://confluence.jetbrains.net/display/Kotlin/Operator+overloading#Operatoroverloading-in


#4

Ahhh wait a minute.

There wasn’t enough indirection there.  It’s when you start mixing generics… for example this (very simplified) example will fail…

``

package runs

fun main(args: Array<String>) {
  println(tests(4).isInRange())
  println(tests(16).isInRange())
}

fun <T> tests(val v: T) : Tests<T>{
  return Tests<T>()
}

class Tests<T>

fun Tests<Int>.isInRange(): Boolean {
  return true
}

fun Tests<Long>.isInRange(): Boolean {
  return true
}

Now isInRange will fail with the duplicate declaration.  Is that due to missing runtime generics?


#5

Yes, you've got the reason right. Exception is caused with the same signatures in bytecode for "isInRange" functions. And they are same becuase of java type erasure mechanism.

Currently we have no good workaround for this problem and that’s why such declarations are forbidden.

(Of course some tricks with writing different signatures to bytecode could be done but such auto rewriting can make kotlin code too unstable to binary compatibity issues).


#6

There's an issue relating to this: http://youtrack.jetbrains.com/issue/KT-1686

Chris