为什么下面的代码在覆盖方法中打印字符串而不是打印“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"
}
}
答案 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))
}