scala中的类型擦除和继承
我有下面的类层次结构scala中的类型擦除和继承,scala,inheritance,type-erasure,Scala,Inheritance,Type Erasure,我有下面的类层次结构 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"
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
继承类之外
另一个缺点是此类后续类的模式匹配有限,即不可能在case
分支中使用此类类,并可能导致混淆错误
例子
您可能期望此代码中没有错误,但您将得到
<console>:17: error: constructor cannot be instantiated to expected type;
found : A
required: B
case A(id) => println(id)
^
所以。。。从case类继承非常容易出错和混淆,除非您知道自己在做什么,否则应该避免使用。据我所知,从case类继承是不推荐的。所以case类只能从常规类继承 执行println通常会调用传递给它的对象上的toString 因此,在您的代码上发生的是,它将调用对象的toString实现,恰好是具有此实现的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)"
}
如果只想获取对象的类型,可以使用getClass
println(d.getClass)
我认为提到这一点会增加答案。@YuvalItzchakov完全同意。我将扩展我的回答,我认为“除非你知道你在做什么”意味着不从case类继承。
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)"
}
println(d.getClass)