Swift do子类继承初始化器?

时间:2015-07-16 15:51:05

标签: ios swift inheritance

我有以下代码:

class Parent {

    var foo: Int

    init(someNum: Int) {
        self.foo = someNum
    }
}

class Child: Parent {

}

var parent = Parent(someNum: 999)
println(parent.foo)                  // prints "999"

var child = Child(someNum: 3872)   
println(child.foo)                   // prints "3872"

在Apple的2014 WWDC“Intermediate Swift”视频中,他说初始化程序默认不会继承,除非它的存储属性有默认值。但是,子类foo中的Child没有默认值,但它明确地继承了init(someNum:)方法。我是否理解错误的解释或是否有其他事情发生?

1 个答案:

答案 0 :(得分:11)

来自Apple文档:

  

默认情况下,子类不会继承其超类初始值设定项。   但是,如果超类初始值设定项会自动继承   满足某些条件。在实践中,这意味着你没有   需要在许多常见场景中编写初始化程序覆盖,并且可以   只要有最小的努力,就可以继承你的超类初始化器   这样做是安全的。

     

假设您为任何新属性提供默认值   在子类中引入,适用以下两个规则:

     

规则1 如果您的子类未定义任何指定的初始值设定项,则为   自动继承其所有超类指定的初始化器。

     

规则2   如果您的子类提供了所有子类的实现   超类指定初始化程序 - 通过按照继承它们   规则1,或通过提供自定义实现作为其一部分   定义 - 然后它自动继承所有的超类   便利初始化者。

     

即使您的子类增加了更多便利,这些规则也适用   初始化。

在您的情况下,您未在Child中提供任何指定的初始值设定项。因此,唯一一个指定的初始值设定项已从Parent继承。

如果您将Child课程修改为:

class Child : Parent {
  var age : Int
  init (age : Int) {
     self.age = age
    super.init(foo: 10)
  }
}

您将看到无法通过调用其超类初始值设定项来创建Child类。 Read more.

修改

上述规则适用于更加不同的情况。也许文档对你来说有点混乱,但让我们停下来想一会儿。你有一个继承自超类的子类,它有一个属性foo。现在,如果您的子类没有添加任何属性,或者添加了带有默认值的属性,则不需要与超类中的初始化程序不同的初始化程序,因此您可以安全地使用它。另一方面,如果添加没有默认值的属性,则无法使用超类中的初始化程序,因为添加的属性需要以某种方式初始化。编译器会抱怨,你必须做以下两件事之一:

  1. 您应该在子类中实现一个指定的初始值设定项,它将分配新属性并调用超类中的指定初始值设定项。
  2. 您可以为您的媒体资源添加默认值,您仍然可以使用超类中指定的初始值设定项。