I can implement nested classes with fluent interfaces in the following fashion:
class Animal(name: String, props: Map[String, Any]) {
def properties: Map[String, Any] = Map("name" -> name) ++ props
def withAge(age: Int): Animal = new Animal(name, props.updated("age", age)) // can't use built-in copy
}
case class Cat(name: String, lives: Int, props: Map[String, Any]) extends Animal(name, props) {
override def properties: Map[String, Any] = Map("name" -> name, "lives" -> lives) ++ props
override def withAge(age: Int): Cat = Cat(name, lives, props.updated("age", age))
}
However I'm far from satisfied by this. There is a lot of repetition and, even if I'm using inheritance, I'm not reusing any code.
I've tried using this.type as a return type and even using zio-prelude subtyping capability but the persistent problem is that, at some point, the subclass doesn't get recognized correctly.
Is there a better way to do this without repetition and leveraging scala features?
Ideally I would like something like this
case class Animal(name: String, props: Map[String, Any]) {
def properties: Map[String, Any] = Map("name" -> name) ++ props
def withAge(age: Int): this.type = copy(props = props.updated("age", age))
}
final case class Cat(name: String, lives: Int, props: Map[String, Any]) extends Animal(name, props + ("lives" -> lives))
so that no duplication is taking place. Of course the following is not compiling though.
val myCat: Cat = Cat("murzic", 9, Map()).withAge(4)