Search code examples
genericskotlinkotlin-generics

Generic function in interface to return concrete implementation


To an interface, I want to add a function that returns an object of the concrete implementation.

So with the interface:

interface Content {
        fun <???> cloneMe(): ?
}

and the classes

class Music: Content
class Video: Content

the function cloneMe() of the Music class should return a Music object and the the function cloneMe() of the Video class should return a Video object.

The closest I've come is:

interface Content {
    fun <T: Content> cloneMe(): T
}

class Music : Content {
    override fun <T : Content> cloneMe(): T {
        return Music() as T
    }
}

then I can do

val music: Music = Music().cloneMe<Music>()

The problem here is that I have to do an unchecked cast, which 'allows me' (i.e. will compile) to do

class Music : Content {
        override fun <T : Content> cloneMe(): T {
            return Video() as T
        }
}

which is problematic.

What's the best way to achieve this?


Solution

  • Typically this is done by parameterizing the Content interface as well, as follows:

    interface Content<T : Content<T>> {
        fun cloneMe(): T
    }
    

    And the implementation:

    class Music : Content<Music> {
        override fun cloneMe(): Music {
            return Music()
        }
    }