在scala中调用方法覆盖

时间:2014-04-17 10:03:00

标签: scala override

为什么下面的代码在覆盖方法中打印字符串而不是打印“test”的原始方法?我已经使用parent指向self并使用parent调用方法

class myClass {
    parent=>
    def method(a:Int):String={
       "test"
    } 
    def run={
        println(parent.method(1))
    }
}   

val testClass=new myClass {
     override def method(a:Int):String={
          "substring"
    }
}

1 个答案:

答案 0 :(得分:4)

在您的示例中,parent标识符只是this对象的另一个名称,指向此对象在运行时的任何指针。 在Scala和Java中(通常在JVM上),在对象上调用方法的规则是调用对象的运行时类型的重写方法。 为此,JVM依赖于virtual function tables将对象类型和方法名称与其特定实现相关联。 这与C ++不同,在C ++中调用对象值(不是指针或引用)的方法将从该对象的编译时类型中解析该方法。

例如,在Scala中你可以这样做:

val compileTimeVar: myClass = new myClass { override def method(a: Int) = "substring" }

从Scala编译器的角度来看,compileTimeVar的类型为myClass。 但是,运行时类型是内部表示为xxx$anon$1的未命名类型,此未命名类型会覆盖method。 主叫:

compileTimeVar.method

如果在该运行时类型中存在,则始终调用重写的方法 - 它将返回"substring"

所谓的self指针与将对象分配给具有丢失的运行时类型信息的变量没有区别 - 您的代码等同于:

class myClass {
  def parent: myClass = this
  def method(a: Int) = "test"
  def run = println(parent.method(1))
}

如果您真的希望run调用method中定义的myClass而不是被覆盖的内容,请执行以下操作:

class myClass {
  private def privateMethod(a: Int) = "test"
  def method(a: Int) = privateMethod(a)
  def run = println(this.privateMethod(1))
}