[英]type erasure and Inheritance in scala
我有以下类层次结构。
trait Item {val id: String}
case class MItem(override val id: String, val name: String) extends Item
class DItem(override val id: String, override val name: String, val name2: String) extends MItem(id, name)
val d = new DItem("1", "one", "another one")
println(d)
预期产出
DItem(1, one, another one)
实际产出
Mitem(1,one)
为什么会这样呢? 建议什么,以便我得到我的对象的真实类型和非类型的超类。
这不是类型擦除。 你得到这个结果是因为DItem
得到了继承自Mitem
toString()
实现。 你必须覆盖它才能得到你想要的东西
class DItem(override val id: String, override val name: String, val name2: String) extends MItem(id, name) {
override def toString = s"DItem($id, $name, $name2)"
}
所以这是一个结果:
scala> val d = new DItem("1", "one", "another one")
d: DItem = DItem(1, one, another one)
scala> println(d)
DItem(1, one, another one)
从case类继承几乎总是一个坏主意,因为除了toString
后继类还将继承equals
和hashCode
。
另一个缺点是对于这样的后继类有限的模式匹配,即在分支的case
不可能使用这样的类并且可能导致混淆的错误。
case class A(id: String)
class B(id: String, name: String) extends A(id)
new B("foo", "bar") match {
case A(id) => println(id)
case other => println(other)
}
您可能希望此代码中没有错误,但您会得到
<console>:17: error: constructor cannot be instantiated to expected type;
found : A
required: B
case A(id) => println(id)
^
但是,如果您明确地推断B
实例的类型,它将起作用
scala> new B("foo", "bar").asInstanceOf[A] match {
| case A(id) => println(id)
| case other => println(other)
| }
foo
所以...从案例类继承是非常容易出错和混乱的,除非你知道你在做什么,否则应该避免。
据我所知,不推荐使用case类继承。 所以case类可以(应该)只从常规类继承。
做println通常会在对象上调用toString传递给它。
所以你的代码会发生什么,它会调用对象的toString实现,恰好是具有这种实现的MItem。
所以你需要覆盖DItem上的toString,如下所示:
class DItem(override val id: String, override val name: String, val name2: String) extends MItem(id, name) {
override def toString = s"DItem($id, $name, $name2)"
}
如果你想获得对象的类型,可以使用getClass。
println(d.getClass)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.