2014-04-17 103 views
1

爲什麼下面的代碼在override方法中打印字符串,而不是打印「test」的原始方法?我已經使用父指向自我和使用的父類調用該方法在scala中覆蓋的調用方法

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" 
    } 
} 

回答

4

在您的示例parent標識符是單純的爲了this對象的指針,不管這個對象是在運行時的另一個名字。 在Scala和Java中(通常在JVM上),在對象上調用方法的規則是調用對象的運行時類型的重寫方法。 爲此,JVM依靠virtual function tables將對象類型和方法的名稱與其特定實現相關聯。 這與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調用定義的methodmyClass而不是任何被重寫,這樣做:

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