我正在使用JavaTpoint练习这段代码来学习Scala中的继承。但是我无法从类的车辆访问成员Bike,其值被初始化为零。我试过超类型引用,但它仍然显示被覆盖的值。为什么它不允许访问超类字段并指向被重写的子类字段(速度)。这是代码和输出。 提前感谢。
class Vehicle {
val speed = 0
println("In vehicle constructor " +speed)
def run() {
println(s"vehicle is running at $speed")
}
}
class Bike extends Vehicle {
override val speed = 100
override def run() {
super.run()
println(s"Bike is running at $speed km/hr")
}
}
object MainObject3 {
def main(args:Array[String]) {
var b = new Bike()
b.run()
var v = new Vehicle()
v.run()
var ve:Vehicle=new Bike()
println("SuperType reference" + ve.speed)
ve.run()
}
}
答案 0 :(得分:4)
此处overriding-vals-in-scala或此处cannot-use-super-when-overriding-values对类似问题的回答是:Scala compiler does not allow to use super on a val
为什么?上面最后一个链接的讨论指向:SI-899。那里的第一条评论说:it was changed so that traits could override vals to be more uniform with classes
答案 1 :(得分:1)
众所周知,在 Scala 编译之后, Scala 将转移到 Java字节码,它与兼容> JVM 即可。
对于课程Vehicle
变量val speed
,在编译之后,它的子类Bike
(protected
变量)可见,我们可以查看bytecode
的{{1}}:
Vehicle
我们可以看到,它在 public Vehicle();
Code:
0: aload_0
1: invokespecial #63 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 10
7: putfield #13 // Field speed:I
10: return
构造函数方法中初始化speed
的值 10 。
我们也可以在Vehicle
构造函数方法中找到init动作:
Bike
它在构造函数方法中为 public Bike();
Code:
0: aload_0
1: invokespecial #67 // Method Vehicle."<init>":()V
4: aload_0
5: bipush 100
7: putfield #13 // Field speed:I
10: return
设置100
。
所以当speed
init
对象时,Bike
字段的值已更新为speed
100
中的superclass
}。所以Vehicle
在那里没有意义。
并且需要调用另一件事:当您在子类super.val
中直接使用super.speed
时,编译器将抛出:
Bike
因此抛出此编译器错误也是由上述原因引起的。