Use extension methods:
open class Foo {
internal var x: Float = 0f
}
fun <T: Foo> T.setX(x: Float): T {
this.x = x
return this
}
open class Bar: Foo() {
internal var z: Float = 0f
}
fun <T: Bar> T.setZ(z: Float): T {
this.z = z
return this
}
class Baz: Bar()
fun test() {
val baz: Baz = Baz().setX(42f).setZ(1337f)
}
I think it’s a pretty cool application of extension methods.
You do have to make your var internal though. If you only use setX
and setZ
from within the class you can move them there and keep the var private.
The second example is trickier, but you can achieve it like in Java:
abstract class Changeable<Self>
where Self: Changeable<Self>
{
var onChange: ((Self) -> Unit)? = null
}
open class StyleBase<Self>: Changeable<Self>()
where Self: StyleBase<Self>
{
fun notifyChanged() {
onChange?.invoke(this)
}
}
class ButtonStyle : StyleBase<ButtonStyle>() {
public var padding: Float = 0f
}
fun test2()
{
val b = ButtonStyle()
b.onChange = { println(it.padding) }
b.padding = 5f
b.notifyChanged()
}
Note you don’t need Changeable
per se, you can roll it into StyleBase
. You need to have these where
clause on the whole hierarchy except at the leaf. In this case it’s okay, but if you want to actually use StyleBase
elsewhere than as the supertype in a class definition, it’s really burdensome. In those case I’d recommend sticking to the casts.
Or wait until there is a real This
type
Myself, I’m more in favour of some form of abstract type (which is really just like a type parameter, except that each class must fix it once and for all and that it hence doesn’t need to be carried around with the type).