使用默认参数覆盖trait方法

时间:2017-05-24 04:57:04

标签: scala

假设以下示例 - 执行时返回 - " 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>();
      ()
    }
  }
}

请详细说明为什么这是预期的行为?

2 个答案:

答案 0 :(得分:5)

因为Scala规范说它应该如何工作。 Section 5.1.4 (Overriding)

  

重写方法从中继承所有默认参数   超类中的定义。通过在。中指定默认参数   覆盖方法可以添加新的默认值(如果是   超类中的相应参数没有默认值)或   覆盖超类的默认值(否则)。

在内部,指向JVM的Scala实现必须将默认参数存储为声明类的成员,因为JVM doesn't directly support default arguments on methods

答案 1 :(得分:0)

Scala 中,默认参数将创建一个默认字段来保存此值,当您调用不带参数的方法时,编译器将自动设置默认参数作为此方法的参数。像:

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

作为反编译代码,默认参数由类Action中设置:

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

当您在没有doSomething的情况下调用parameter s方法时,它正在调用:

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

使用默认参数revokeAction.doSomething$default$1(),因为RevokeAction不是override def doSomething$default$1(),所以默认参数仍为father

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