我知道你不允许继承案例类,但是当你真的需要时你会怎么做?我们在层次结构中有两个类,它们都包含许多字段,我们需要能够创建两个类的实例。这是我的选择:
我该怎么办?这不是一个常见的问题吗?
答案 0 :(得分:10)
是的,这是一个经常出现的问题,我建议使用所有父属性创建一个特征,创建一个只实现它的案例类,然后再创建另一个具有更多属性的案例类。
sealed trait Parent {
/* implement all common properties */
}
case class A extends Parent
case class B extends Parent {
/*add all stuff you want*/
}
看到它的好方法是树,特征是节点,案例类是叶子。
您可以根据父母的需要使用特质或抽象类。但是,避免使用类,因为您可以创建它的实例,这不是很优雅。
编辑:正如评论中所建议的那样,如果并非所有案例类都包含在模式匹配中,您可以密封特征以便在编译时出现异常。例如,“Scala编程”第15.5章对此进行了解释
答案 1 :(得分:6)
如何用委托替换继承?
如果层次结构中的两个类有许多共享字段,那么委托可以减少样板代码的数量吗?像这样:
case class Something(aa: A, bb: B, cc: C, payload: Payload)
sealed abstract class Payload
case class PayloadX(xx: X) extends Payload
case class PayloadY(yy: Y) extends Payload
然后你会像这样创建Something
个实例:
val sth1 = Something('aa', 'bb', 'cc', PayloadX('xx'))
val sth2 = Something('aa', 'bb', 'cc', PayloadY('yy'))
你可以进行模式匹配:
sth1 match {
case Something(_, _, _, PayloadX(_)) => ...
case Something(_, _, _, PayloadY(_)) => ...
}
好处:(?)
当您声明 PayloadX 和 PayloadY 时,您不必重复 Something 中的所有字段。
当您创建Something(... Payload(..))
的实例时,您可以在创建Something
和Something(... PayloadX(..))
时重复使用创建...PayloadY
的代码。
缺点:(?)
在您的案例中,PayloadX
和Y
实际上可能是Something
的真正子类,我的意思是,在您的情况下,或许委托在语义上是错误的?
你必须写something.payload.whatever
而不是something.whatever
(我想根据你的具体情况,这可能是好还是坏?)
答案 2 :(得分:3)
我也探讨过这个问题,AFAIK,你得到的最好的是:
让每个案例类从定义抽象的共同特征扩展 每个案例类必须实现的属性
它不会删除样板(根本没有),但定义了你的案例类必须遵守的契约,同时不会丢失案例类功能集......