kotlindelegation

Issue with Kotlin Interface Delegation int toString/equals/hash functions


Lets asume that we have following interface with a concrete class:

interface Foo {
    fun getString():String
}
class FooImpl : Foo {
    private val amber = "Hello Amber!"
    override fun getString(): String {
       return amber
    }
    override fun toString(): String {
        return amber
    }
}
class FooWrapper(foo: Foo): Foo by foo

then we run this with:

 val fooImpl = FooImpl()
 val fooWrap = FooWrapper(fooImpl)
 println("${fooImpl.toString()} vs ${fooWrap.toString()}")
 println("${fooImpl.getString()} vs ${fooWrap.getString()}")

and we get

Hello Amber! vs test.myapplication.FooWrapper@90db1fa
Hello Amber! vs Hello Amber!

Why .toString is also not delegated?


Solution

  • Taken from Kotlin docs, where i changed the names according to your example:

    The by-clause in the supertype list for FooWrapper indicates that foo will be stored internally in objects of FooWrapper and the compiler will generate all the methods of Foo that forward to foo.

    Essentially meaning: "Everything declared in the interface gets forwarded". You did not declare toString (or the other methods) as part of the interface and thus no automatic forwarding will happen.

    Add explicit references to resolve that issue:

    interface Foo {
        fun getString():String
        override fun toString(): String
    }
    

    Notice that you will need to specify override.