让我们假设我们有以下两个类:
abstract case class MyParent(param: Int) {
// ...
}
case class MyChild(param: Int) extends MyParent(param: Int) {
// ... ^^^^^ ^^^^^
}
将它们作为案例类导致两个param
使用位置都出错,这表示它需要覆盖父类值的override
修饰符。这对我来说很奇怪..为什么我必须在这里发明其他的param名称..为什么这个事情的顺序是强制执行的?利润在哪里?
答案 0 :(得分:7)
你永远不应该从另一个案例类派生一个案例类!
在以 scala -deprecation 开头的REPL中尝试此操作:
scala> case class Foo(foo: String)
defined class Foo
scala> case class Bar(override val foo: String) extends Foo(foo)
<console>:9: warning: case class `class Bar' has case ancestor `class Foo'. Case-to-case inheritance has potentially dangerous bugs which are unlikely to be fixed. You are strongly encouraged to instead use extractors to pattern match on non-leaf nodes.
答案 1 :(得分:1)
快速修复此问题
abstract case class MyParent(param: Int) {
println("Form parent : " + param)
}
case class MyChild(override val param: Int) extends MyParent(param) {
println("Form child : " + param)
}
val c = MyChild(10);
这将导致此
>> From parent : 10
>> From child : 10
实际上extends MyParent()
与Java不同。这是一种告诉MyChild
extends MyParent
的方法,并且首先调用后者的超级构造函数。
答案 2 :(得分:1)
利润在哪里?
缺少一个不太有用的特殊情况。 param
中的case class MyChild(param: Int)
是一个类成员以及一个构造函数参数,因此其中一个祖先已经有一个(非抽象)param
成员,必须重写它。
答案 3 :(得分:1)
就我有限的Scala知识而言,案例类通常用于不可变的代数数据类型和模式匹配。因此,您可能应该创建一个包含“父”类的类,而不是创建“子类”。
> case class MyParent(param: Int)
defined class MyParent
> case class MyChild(param: Int, parent: MyParent)
defined class MyChild
> def foo(c: MyChild) = c match {
case MyChild(p, MyParent(p2)) => println("p: " + p + ", p2 " + p2)
}
foo: (c: MyChild)Unit
> foo(MyChild(3, MyParent(4)))
p: 3, p2 4