Scala:向 super 方法添加可选参数

标签 scala inheritance

我正在尝试实现如下特征:(1)

trait FooLike {
  def foo(x: Int): Int
}

class Foo extends FooLike {
  def foo(x: Int, y: Int = 0): Int = x + y
}

但是编译器提示方法 foo(x: Int): Int 未实现。

我能做到:(2)

class Foo extends FooLike {
  def foo(x: Int): Int = foo(x, 0)
  def foo(x: Int, y: Int = 0): Int = x + y
}

但是感觉像Java,我不喜欢它!有没有办法避免这个样板?

我认为 def foo(x: Int, y: Int = 0) 会在后台定义两个方法,但显然事实并非如此。到底发生了什么?

--- 编辑:更奇怪 ---

以下内容也是完全合法的:(3)

class Foo extends FooLike {
  def foo(x: Int): Int = x - 1
  def foo(x: Int, y: Int = 0): Int = x + y
}

虽然这看起来不合理(foo(4) = 3 while foo(4, 0) = 4)。

我认为授权(1)和禁止(3)本来是最合理的选择,但他们却做出了相反的选择。那么 Scala 为何做出这些选择呢?

最佳答案

在 Scala 中,无法使用默认参数覆盖不同类型签名的方法。这是因为默认参数的实现方式。默认参数是在应用方法的时间和位置插入的,因此只有一个版本的方法被定义。

根据SID-1: Named and Default Arguments ,当编译带有默认参数的方法 foo() 时,仅定义一个方法 foo(),它接受所有参数。使用默认参数(例如 f.foo(xValue))的调用在编译时会转换为与以下内容等效的代码:

{
  val x = xValue
  val y = f.foo$default$2
  f.foo(x, y)
}

foo$default$2 方法是一个隐藏方法,它不带任何参数,并将参数 #2 的默认值返回给方法 foo()

因此,虽然您可以为方法 foo(x: Int) 或方法 foo(x: Int) 编写完全相同的函数应用程序 foo(xValue) Int, y: Int = 0),“在幕后”调用的方法不具有相同的类型签名。

关于Scala:向 super 方法添加可选参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25208080/

相关文章:

scala - 如何在scala中对列表列表执行转置?

scala - : _* notation in scala

C++:条件继承是否可能

c++ - 在 C++ 中访问基类私有(private)成员

scala - 如何让 Squeryl 与 Play 一起工作!框架?

java - 如何管理来自在单独线程中运行的多个外部命令的多个标准输出?

c++ - 如何在层次结构中实现运算符使用?

sql - 仅将表用于多重继承是一种不好的做法吗?

postgresql - 光滑的查询非常慢

c# - 为什么当对象是子类类型时,不能从父类(super class)中调用子类中的公共(public)方法?