2017-05-24 9 views
1

次の例を想定 - リターンを実行したとき - 「fatherfather」デフォルトパラメータで形質メソッドをオーバーライド

trait Action { 
    def doSomething(s:String = "father") = s 
} 

class RevokeAction extends Action{ 
    override def doSomething(s:String) = { 
     s + s 
    } 
} 

object HelloWorld { 
    def main(args: Array[String]): Unit = { 
    val revokeAction = new RevokeAction() 
    revokeAction.doSomething() 
    } 
} 

コンパイラが何をするかを見てみると -

package <empty> { 
    abstract trait Action extends Object { 
    def doSomething(s: String): String = s; 
    <synthetic> def doSomething$default$1(): String = "father"; 
    def /*Action*/$init$(): Unit = { 
    () 
    } 
    }; 
    class RevokeAction extends Object with Action { 
    <synthetic> def doSomething$default$1(): String = RevokeAction.super.doSomething$default$1(); 
    override def doSomething(s: String): String = s.+(s); 
    def <init>(): RevokeAction = { 
     RevokeAction.super.<init>(); 
     RevokeAction.super./*Action*/$init$(); 
    () 
    } 
    }; 
    object HelloWorld extends Object { 
    def main(args: Array[String]): Unit = { 
     val revokeAction: RevokeAction = new RevokeAction(); 
     { 
     revokeAction.doSomething(revokeAction.doSomething$default$1()); 
     () 
     } 
    }; 
    def <init>(): HelloWorld.type = { 
     HelloWorld.super.<init>(); 
    () 
    } 
    } 
} 
に何が起こっているのより良い説明を与えます

これが期待される動作である理由を詳しく教えてください。 スカラ、デフォルトのパラメータで

答えて

3

それはScalaの仕様は、それが動作するはずと言う方法ですので。 Section 5.1.4 (Overriding)

スーパーで 定義からすべてのデフォルト引数を継承しオーバーライドするメソッド。 オーバーライドメソッドでデフォルトの引数を指定すると、スーパークラスのデフォルトをオーバーライドするために、新しいデフォルトを追加することができます( の対応するスーパークラスに対応するパラメータにデフォルトがない場合)または を追加することができます。

JVMを指示するScalaの実装は、JVM doesn't directly support default arguments on methods以降、デフォルトのパラメータを宣言クラスのメンバとして格納する必要があります。

+1

仕様でその見落としがありました - ありがとうございました! –

+0

"を宣言クラスの定数メンバとして"メソッドを意味すると思います。 –

+0

@AlexeyRomanov "declaring class"とは、デフォルトのパラメータを持つメソッドが宣言されたクラスを意味します。 –

0

は、この値を維持するために、デフォルトのフィールドを作成し、あなたはパラメータなしでメソッドを呼び出すときに、コンパイラが自動的にこのメソッドのパラメータとしてデフォルトパラメータを設定します。以下のような:

revokeAction.doSomething(revokeAction.doSomething$default$1()); 

あなたの逆コンパイルコード、デフォルトのパラメータはクラスAction中でsettedされたよう:

<synthetic> def doSomething$default$1(): String = "father"; 

、あなたがparameter sなしdoSomethingメソッドを呼び出すときに、それが呼び出しています:

revokeAction.doSomething(revokeAction.doSomething$default$1()); 

デフォルトパラメータrevokeAction.doSomething$default$1()、以降はないoverridedef doSomething$default$1()ので、デフォルトパラメータがまだfather次のとおりです。

<synthetic> def doSomething$default$1(): String = RevokeAction.super.doSomething$default$1(); 
関連する問題