---
description: >-
  Automatic Initializer Inheritance：🤔 一個子類別 (subclass) 何時會繼承母類別 (superclass)
  的初始化程序❓
---

# 自動繼承初始化程序

## ⭐️ 繼承規則

一般來說，**subclass** 並**不會繼承** superclass 的 **initializers**，但如果**符合以下的狀況**則會自動繼承：

1. 如果 **subclass** 為自己**所有的屬性** (**stored properties**) 提供**預設值** (**default values**)，這時 superclass initializers 依然可以正常運作，因此 subclass 就會**自動繼承**所有的 (designated & convenience) initializers。
2. 如果 subclass 定義了自己的屬性但卻**沒有給預設值**，這時會造成 superclass initializers 不知如何處理這些屬性 (因為 superclass 根本無從得知這些屬性的存在)，這時 subclass 就會**喪失所有的** superclass initializers。
3. 但如果 subclass 又實作 (implement/override) 了**所有的 superclass designated initializers**，這時 subclass 又會**重新繼承**所有的 superclass **convenience** initializers。

![Class Initializer Inheritance](https://1830103165-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M5-JmwCZMKh_d7RfBaN%2F-M5HsRvDsSfKARc_stzF%2F-M5HzpHsmavi0Zu8zNzX%2Fclass%20init%20inherit.jpg?alt=media\&token=76527805-8ce2-47b7-8d72-b3aa18408d49)

## ⭐️ 重點整理

* 如果 **subclass** 有定義自己的 **convenience** initializers，則上述的規則**依然成立**。
* 在實作 **superclass designated** initializers 的時候，如果用 `override convenience init` 的方式，而不是用 `override init` (**override designated** initializer) 的方式，可以減少 **subclass designated** initializers 的數量。 :arrow\_right: [convenience override](https://livebook.manning.com/book/swift-in-depth/chapter-5/113)

## 💈範例

{% tabs %}
{% tab title="main" %}
```swift
// superclass instance
let p = Person(name: "Tom", age: 20)
print(p.age)      // 20

/*  subclass instances  */

// Student
// ---------------------------------------------
// (o) default values for new properties
// (o) no custom designated inits.
//  -> inherits all designated/convenience inits
let s1 = Student(name: "May", age: 17)  // inherited designated init
let s2 = Student(name: "Baby")          // inherited convenience init
let s3 = Student(seatNo: 23)            // custom convenience init
print(s1.seatNo)  // 50
print(s2.age)     // 0
print(s3.name)    // "no name"

// Teacher
// ----------------------------------------------
// (o) default values for new properties
// (x) no custom designated inits.
// (o) implements all superclass designated inits
//  -> inherits all superclass convenience inits.
let t1 = Teacher(name: "Joe", age: 35, title: "Dr.")  // custom designated init
let t2 = Teacher(name: "Joe", age: 35)                // override superclass init
let t3 = Teacher(name: "Babe")                        // inherited convenience init
print(t1.title)   // "Dr."
print(t2.title)   // "Mr./Ms."
print(t3.age)     // 0

// Master
// -----------------------------------------------
// (x) default values
//  -> does not inherit superclass initializers
let m = Master(name: "Sheefu", age: 100, skill: "Kung Fu")  // custom designated init
print(m.skill)    // "Kung Fu"
```
{% endtab %}

{% tab title="Person" %}
```swift
// superclass
class Person {

  // stored properties
  var name: String
  var age : Int

  // designated: init(name:age:)
  init(name:String, age:Int){
    self.name = name
    self.age  = age
  }

  // convenience: init(name:)
  convenience init(name:String){
    self.init(name: name, age: 0)
  }

}
```
{% endtab %}

{% tab title="Student" %}
```swift
// (o) default values for new properties
// (o) no custom designated inits.
//  -> inherits all designated/convenience inits
class Student: Person {
  // stored properties with default values
  var seatNo: Int = 50
}

extension Student {
  // custom convenience init
  convenience init(seatNo: Int) {
    // calls inherited designated init
    self.init(name: "no name", age: 16)
    self.seatNo = seatNo
  }
}
```
{% endtab %}

{% tab title="Teacher" %}
```swift
// (o) default values for new properties
// (x) no custom designated inits.
// (o) implements all superclass designated inits
//  -> inherits all superclass convenience inits.
class Teacher: Person {

  var title: String = "Mr./Ms."

  // custom designated init
  init(name: String, age: Int, title: String) {
    self.title = title
    super.init(name: name, age: age)
  }

  // superclass designated -(override)-> subclass convenience
  override convenience init(name: String, age: Int) {
    self.init(name: name, age: age, title: "Mr./Ms.")
  }

}
```
{% endtab %}

{% tab title="Master" %}
```swift
// (x) default values
//  -> does not inherit superclass initializers
class Master: Person {
  var skill: String
  // custom designated init
  init(name: String, age: Int, skill: String){
    self.skill = skill
    super.init(name: name, age: age)
  }
}
```
{% endtab %}
{% endtabs %}

:link: 原始碼：[Repl.it](https://repl.it/@pegasusroe/Class-Init-Inheritance)

{% hint style="info" %}
📘 參考資料

1. [Swift in Depth, Ch.5 Demistifying Initializers](https://livebook.manning.com/book/swift-in-depth/chapter-5/)
2. [Initialization - Swift](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html)
{% endhint %}
