为什么可以在子类型的重载成员函数中省略默认值?

正如在标题中所述:为什么可以在子类型的重载成员函数中省略默认值?

这是正常的还是预期的?

interface Foo { fun bar(parameter: Int = 1) } class Baz : Foo { override fun bar(parameter: Int) { // OK println(parameter) } } val baz = Baz() baz.bar() // OK baz.bar(2) // OK 

Foo是一个类的情况下也是同样的行为。

这是正常的还是预期的?

是。

我怀疑这主要是一个语言设计/可用性决定。 从这个角度来看,有四个选项可用:

  1. 只声明超类型。
  2. 只声明子类型。
  3. 在两个声明中,但不允许子类型更改默认值。
  4. 在两个声明中,允许子类型覆盖超类型的默认值。

Kotlin设计师选择了选项#1。 这是有道理的,因为:

选项#2和#4都暗示调用者不知道默认值是什么,除非他们知道他们正在使用哪个实现,这当然是非常不可取的。 调用者需要额外的逻辑来确定是否需要一个值来覆盖默认值,这意味着默认值将是无用的。

选项#3违反了DRY原则。 为什么迫使宣言在两个地方?

这使得选项#1成为唯一的选择。

是的,这是正常的和可以预料的。

更重要的是,不允许覆盖默认值。 这不会编译:

 interface Foo { fun bar(parameter: Int = 1) } class Baz : Foo { override fun bar(parameter: Int = 1) { // ERROR: An overriding function is not allowed to specify default values for its parameters } } 

从技术上讲,使用固定默认值的实现比任何其他实现都简单得多。 例如,Scala很大程度上提供了这种功能,但生成的字节码不是一个简单的。