Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 434
fweigl Avatar asked Dec 13 '17 15:12

fweigl


1 Answers

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()
    }
}
like image 179
hotkey Avatar answered Nov 02 '22 23:11

hotkey