简体   繁体   中英

Overriding trait method with default parameter

Assume the following example - when executed returns - "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()
  }
}

Looking at what the compiler does - gives a better explanation of what is going on

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>();
      ()
    }
  }
}

Can please elaborate why this is the expected behavior?

Because that is how the Scala specification says it should work. Section 5.1.4 (Overriding) :

An overriding method inherits all default arguments from the definition in the superclass. By specifying default arguments in the overriding method it is possible to add new defaults (if the corresponding parameter in the superclass does not have a default) or to override the defaults of the superclass (otherwise).

Internally, Scala implementation which directs the JVM has to store the default parameter as a member of the declaring class, since the JVM doesn't directly support default arguments on methods .

In Scala , the default parameter, will create a default field to keep this value, and when you call the method without parameter, the compiler will auto set the default parameter as this method's parameter. like:

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

As your decompile code, The default parameter is setted by in class Action :

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

and when you call doSomething method without parameter s , it's calling:

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

with the default parameter : revokeAction.doSomething$default$1() , since RevokeAction not override def doSomething$default$1() , so default parameter is still father :

<synthetic> def doSomething$default$1(): String = RevokeAction.super.doSomething$default$1();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM