Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial class delegation in Kotlin

How do I partial delegate methods/fields in Kotlin?

To be specific: here I am trying to inherit class User from interface TraitA and implement field marked: Boolean in the wrapper StateA. That would clean up the User implementation, because marked is just a state field. Note that TraitA can't be a class because I want to use several such interfaces: User() : TraitA by StateA, TraitB by StateB, ..

/* does not compile (Kotlin M12) */
interface TraitA {
    var marked: Boolean

    fun doStaffWithMarked()  // must be overridable
}

class StateA() : TraitA {
    override var marked = false
}

class User() : TraitA by StateA(){
    override fum doStaffWithMarked() {
        //...all fancy logic here...
    }
}

The alternative is to implement all in one place:

class User() : TraitA{
    override var marked = false // ugly code

    override fum doStaffWithMarked() {
        //...
    }
}

Is there a way/pattern that would solve that problem with easy and as little code as possible? Code/bytecode generation is not an option for me.

UPDATE

I was not very clear about that, but please note that doStaffWithMarked() is unique for every User.

So I may suggest a 'half-bad' solution with run-time assertions:

interface TraitA {
    var marked: Boolean

    /* must be overridden */
    fun doStaffWithMarked() = throw UnsupportedOperationException()
}

class StateA() : TraitA {
    override var marked = false
}

class User() : TraitA by StateA() {
    override fum doStaffWithMarked() {
        //...all fancy logic here...
    }
}

The question is still open, since a really good solution would check that doStaffWithMarked() at compilation time.

like image 959
voddan Avatar asked Jun 17 '15 21:06

voddan


1 Answers

Split up TraitA into two interfaces, then delegate the one and implement the other:

interface TraitA {
    var marked: Boolean
}

interface TraitAPlus : TraitA {
    fun isMarked(): Boolean
}

class StateA() : TraitA {
    override var marked = false
}

class User() : TraitA by StateA(), TraitAPlus {
    override fun isMarked(): Boolean {
        return marked
    }
}
like image 160
Kirill Rakhman Avatar answered Oct 08 '22 00:10

Kirill Rakhman