Carat Syntax in Kotlin Interfaces

Viewed 101

May help to explain this just a bit.

Say I have an abstract class called Page that looks like so:

abstract class Page {
    abstract fun title() : String
}

And an interface called Book:

interface Book {
    fun write(page: Page)
    fun read(title: String) Page
}

My question is how can I use the carat generic syntax to specify that the methods must be used by derived instance of the Page class. Maybe like this:

interface Book<Page> {
    fun write(page: Page)
    fun read(title: String) : Page
}

class AdventureBookPage(val pageTitle: String, val content: String) : Page() {

    override fun title() : String {
        return title
    }
}

class AdventureBook : Book<AdventureBookPage> {
    override fun write(abp: AdventureBookPage) {
        // do writing ops
    }
    override fun read(title: String) : AdventureBookPage {
        // do read ops
    }
}

Am I misunderstanding how generics work here? Any help would be very much appreciated.

2 Answers

Am I misunderstanding how generics work here?

Yes, a little.

interface Book<Page> {
    fun write(page: Page)
    fun read(title: String) : Page
}

What you've essentially declared here is this:

interface Book<Foo> {
    fun write(page: Foo)
    fun read(title: String) : Foo
}

Page was just an identifier, representing any old type. You could make a Book<String>, a Book<HttpClient> or a Book<ArrayList<String>>. Ordinarily, rather than Foo or Page, the identifier T is used, standing for 'type'.

The fact that the identifier matches a type you've created yourself is only incidental.

What I suppose you were trying to declare was that a book is a collection of pages, or anything more specialised than a page. This is called a 'generic constraint', and you would express that like so:

interface Book<T : Page> {
    fun write(page: T)
    fun read(title: String) : T
}

You can use the kotlin constraints, specifically Upper bounds:

interface Book<T : Page> {
    fun write(page: T)
    fun read(title: String) : T
}

docs here

Related