斯卡拉:为什么我们不能做超级计划?

时间:2017-08-29 09:40:01

标签: scala override instance access member

我正在使用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()
  }
}

How do I get the result using instance of Bike.

2 个答案:

答案 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,在编译之后,它的子类Bikeprotected变量)可见,我们可以查看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

因此抛出此编译器错误也是由上述原因引起的。