为什么可以在子types的重载成员函数中省略默认值?
正如在标题中所述:为什么可以在子types的重载成员函数中省略默认值?
这是正常的还是预期的?
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
是一个类的情况下也是同样的行为。
这是正常的还是预期的?
是。
我怀疑这主要是一个语言设计/可用性决定。 从这个角度来看,有四个选项可用:
- 只声明超types。
- 只声明子types。
- 在两个声明中,但不允许子types更改默认值。
- 在两个声明中,允许子types覆盖超types的默认值。
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很大程度上提供了这种function,但生成的字节码不是一个简单的。