【发布时间】:2021-10-28 00:28:04
【问题描述】:
我可以通过以下方式实现具有流畅接口的嵌套类:
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))
}
但我对此并不满意。有很多重复,即使我使用继承,我也不会重用任何代码。
我尝试使用this.type 作为返回类型,甚至使用zio-prelude 子类型功能,但一直存在的问题是,在某些时候,子类无法正确识别。
有没有更好的方法来做到这一点而无需重复和利用 scala 功能?
理想情况下我想要这样的东西
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))
这样就不会发生重复。当然,以下内容没有编译。
val myCat: Cat = Cat("murzic", 9, Map()).withAge(4)
【问题讨论】:
-
如果您使用案例类,.copy() 方法是开箱即用的,这就是为什么 .copy() 在您的动物类中不起作用的原因。在你的
Cat类中,当你扩展 Animal 类时,你可以像这样:extends Animal(name, props + ("lives" -> lives))并摆脱第一个方法覆盖。 -
您的问题只是缺少通用的深度克隆方法。有很多方法可以实现它,但大多数都涉及某种序列化。虽然我知道这可能是一个玩具示例,但它看起来有点奇怪。为什么需要显式不变性?这看起来很像建造者模式,你真的需要建造者吗?
标签: scala scala-cats zio