I have following java classes I can't change
interface Parent...
class Child1Class implements Parent...
class Child2Class implements Parent...
class GrandChild1Class extends Child1Class ...
...
Now I write Kotlin application.
I want to add some functionality to all the hierarchy.
fun Parent.foo(){ println("Parent.foo")
but I want to have special behaviour for GrandChild1Class
fun GrandChild1Class.foo(){ println("GrandChild1Class.foo")
But if I write:
val grandChild1: Parent = GrandChild1Class()
grandChild1.foo()
I see Parent.foo because of reference type
But I expected to see GrandChild1Class.foo
Is there way to achieve polymorphic behavior for such kinda things ?
No. Kotlin implements extension functions as static Java methods, with the receiver of the extension function being the first parameter of the Java method.
becomes
Of course, static methods are statically dispatched, so there is no polymorphism.
The simple workaround is to just check the type with a
when.The only instructions in the JVM that can dynamically dispatch methods are
invokeinferface,invokevirtual, andinvokedynamic. The first two both require the method to be declared in the class/interface of the instance the method is called, which extension methods cannot do. i.e. declaringfun String.foo()in Kotlin can't possibly add afoomethod tojava.lang.String.The Kotlin compiler can in theory use
invokedynamic. It would find all the applicable extension methods, do some overload resolution, and return aCallSitecorresponding to a particular extension method it found. In practice, this would require a lot of designing to figure out what the exact behaviours should be, as well as big changes to the compiler, and breaking source-compatibility.