https://kotlinlang.org logo
#getting-started
Title
# getting-started
r

Rob Elliot

11/30/2023, 6:16 PM
I'm trying to decorate a Java class that isn't mine by extending it but making all the methods delegate to a different instance. Unfortunately the class has method pairs for java primitives and non-primitives -
setInt(Integer value)
&
setInt(int value)
. They both override to the same signature in Kotlin... Is there an escape hatch?
s

Shawn

11/30/2023, 6:23 PM
what's the issue you're running into? If you implement just one, you should be covered on implementing both
If you need to implement both, I think you should be able to overload with
Int
and
Int?
r

Rob Elliot

11/30/2023, 6:33 PM
The issue is that I then pass an instance to java code which calls both. but only one hits my overridden method, the other goes to the super class. This:
Copy code
class Decorator : BaseClass() {
  val delegate = BaseClass()

  override fun setInt(integer: Int?) { delegate.setInt(integer) }

  override fun setInt(integer: Int) { delegate.setInt(integer) }
}
results in this error:
Copy code
e: file:///Decorator.kt:6:12 Accidental override: The following declarations have the same JVM signature (setInt(Ljava/lang/Integer;)V):
    fun setInt(integer: Int?): Unit defined in io.mocklab.host.openapi.linenumbers.Decorator
    fun setInt(integer: Int?): Unit defined in io.mocklab.host.openapi.linenumbers.Decorator
OK, some testing suggests that if I override as so:
Copy code
class Decorator : BaseClass() {
  val delegate = BaseClass()

  override fun setInt(integer: Int) { delegate.setInt(integer) }
}
then Java code calling
setInt
will be routed to this method whether an
Integer
or an
int
is supplied as the argument, so at least I'm always intercepting it. Still not great - if I make the parameter nullable then calls with an
int
are not intercepted, but if it's not nullable calls with
null
blow up with an NPE.
e

ephemient

12/01/2023, 1:37 AM
it's ugly but this will allow for overriding them separately:
Copy code
class Decorator : BaseClass() {
    val delegate = BaseClass()

    @Suppress("ACCIDENTAL_OVERRIDE")
    @JvmName("setInt")
    fun setPrimitiveInt(integer: Int) {
        delegate.setInt(integer)
    }

    @Suppress("ACCIDENTAL_OVERRIDE")
    @JvmName("setInt")
    fun setBoxedInt(integer: Int?) {
        delegate.setInt(integer)
    }
}
🆒 4
r

Rob Elliot

12/01/2023, 9:30 AM
Thanks, that's exactly the sort of escape hatch I was looking for!
3 Views