# required initializer

[swift](https://lochiwei.gitbook.io/ios/swift) ⟩ [type](https://lochiwei.gitbook.io/ios/swift/type) ⟩ [init](https://lochiwei.gitbook.io/ios/swift/type/init) ⟩ [initializers](https://lochiwei.gitbook.io/ios/swift/type/init/initializers) ⟩ required&#x20;

{% hint style="success" %}
1️⃣ write <mark style="color:blue;">`required`</mark> before the definition of a [class](https://lochiwei.gitbook.io/ios/swift/type/category/basic/class) initializer to indicate that <mark style="color:yellow;">every</mark> <mark style="color:orange;">subclass</mark> <mark style="color:yellow;">of the class must implement that initializer</mark>. ( :point\_right: 💈範例 (1) )

2️⃣ write <mark style="color:blue;">`required`</mark> before <mark style="color:yellow;">every</mark> <mark style="color:orange;">subclass</mark> <mark style="color:yellow;">implementation</mark> of a *<mark style="color:purple;">required initializer</mark>*, <mark style="color:red;">don’t</mark> <mark style="color:yellow;">write</mark> <mark style="color:red;">`override`</mark> when <mark style="color:orange;">overriding</mark> a *<mark style="color:purple;">required</mark>* <mark style="color:orange;">designated initializer</mark>.
{% endhint %}

{% hint style="warning" %}
You <mark style="color:red;">don’t</mark> <mark style="color:yellow;">have to</mark> provide an <mark style="color:yellow;">explicit implementation</mark> of a *<mark style="color:purple;">required initializer</mark>* if you can satisfy the requirement with an <mark style="color:orange;">inherited initializer</mark>. ( :point\_right: 💈範例 (2) )
{% endhint %}

{% tabs %}
{% tab title="💾 語法" %}

```swift
// superclass
class SuperClass {
    required init() { ... }    // 1️⃣ required (designated) init
}

// subclass
class Subclass: SuperClass {
    required init() { ... }    // 2️⃣ required init (No `override` here❗️)
}
```

{% endtab %}

{% tab title="💈範例" %}
{% tabs %}
{% tab title="1" %}
下面的例子說明：如果 <mark style="color:orange;">subclass</mark> 沒有提供 <mark style="color:blue;">`required init`</mark> 會發生什麼錯誤，以及如何解決它。

```swift
// superclass
class BasePoint {

    var x: Double
    var y: Double
    
    // ⭐️ required (designated) init
    required init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }
}

// subclass
class ColoredPoint: BasePoint {

    var color: String
    
    // ⛔ error: 'required' initializer 'init(x:y:)' must be provided 
    //    by subclass of 'BasePoint'.
    
    // required (designated) init
    required init(x: Double, y: Double, color: String = "black") {
        self.color = color
        super.init(x: x, y: y)
    }
}
```

我們可以在 <mark style="color:orange;">subclass</mark> 提供一個 <mark style="color:blue;">`required init`</mark> (<mark style="color:orange;">require designated initializer</mark>)，來解決這個問題：

```swift
// 方法一：required designated init
// ⭐️ subclass must implement required init
required init(x: Double, y: Double) {
    self.color = "black"    // ⭐️ init self's properties first
    super.init(x: x, y: y)  // ⭐️ init super's properties next
}
```

或者也可以提供一個 <mark style="color:blue;">`required convenience init`</mark>，然後<mark style="color:yellow;">將真正初始化的工作交給自己的</mark> <mark style="color:blue;">`required init`</mark>：

```swift
// 方法二：required convenience init
required convenience init(x: Double, y: Double) {
    // ⭐️ delegates to self's required init
    self.init(x: x, y: y, color: "black")
}
```

{% hint style="danger" %}
但千萬<mark style="color:red;">不能用</mark> <mark style="color:blue;">`required init`</mark> (<mark style="color:orange;">require designated initializer</mark>)，然後<mark style="color:yellow;">將初始化的工作交給自己的</mark><mark style="color:red;">另一個</mark> <mark style="color:blue;">`required init`</mark>❗

```swift
// required (designated) init but delegates❗
required init(x: Double, y: Double) {
    // ⛔ error: 
    // designated initializer cannot delegate (with 'self.init')
    self.init(x: x, y: y, color: "black")
}
```

{% endhint %}
{% endtab %}

{% tab title="2" %}
當<mark style="color:orange;">子類別</mark> 1️⃣ <mark style="color:yellow;">沒有新屬性</mark> 2️⃣ 也<mark style="color:yellow;">不需修改</mark><mark style="color:orange;">父類別</mark><mark style="color:yellow;">的初始化邏輯</mark>時，則不需實作自己的 <mark style="color:blue;">`required init`</mark>，用[繼承](https://lochiwei.gitbook.io/ios/swift/type/inheritance)來的就可以了。

```swift
// BaseClass
class BaseClass {

    var x: Int
    var y: Int
    
    required init(x: Int, y: Int) {
        self.x = x
        self.y = y
    }
}

// SubClass
class SubClass: BaseClass {
    // ⭐️ 子類別沒有新屬性，不需實作 `required init`。
    func idle() { /* do nothing */ }
}

let obj = SubClass(x: 10, y: 20)

print(obj.x)    // 10
print(obj.y)    // 20
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="📘 手冊" %}

* [Swift](https://docs.swift.org/swift-book/documentation/the-swift-programming-language) ⟩ [Initialization](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization/) ⟩
  * [Required Initializers](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization/#Required-Initializers)
    {% endtab %}
    {% endtabs %}
