[Swift] クラスのイニシャライザ５： required 修飾子

# はじめに

この記事では、required 修飾子について説明します。


# 他の記事へのリンク

* [[Swift] クラスのイニシャライザ１： イニシャライザの引数の書き方](http://qiita.com/cotrpepe/items/bfebe21e9f75c1fce60c)
* [[Swift] クラスのイニシャライザ２： プロパティの初期化方法](http://qiita.com/cotrpepe/items/db842f74b4c8ce16052c)
* [[Swift] クラスのイニシャライザ３： Designated Initializer と Convenience Initializer](http://qiita.com/cotrpepe/items/3052d91468f1b852582a)
* [[Swift] クラスのイニシャライザ４： override 修飾子](http://qiita.com/cotrpepe/items/8d197a9a288eb24c19fb)
* [[Swift] クラスのイニシャライザ５： required 修飾子](http://qiita.com/cotrpepe/items/3931c0c20ef43f4a18ac)
* [Swift] クラスのイニシャライザ６： Failable Initializer


# 環境

* Xcode 6.1 (Playground)


# required 修飾子とは？

required 修飾子は、以下の２つの状況で使います。

* 状況１） サブクラスにイニシャライザのオーバーライドを強制するとき
* 状況２） プロトコルのイニシャライザをオーバーライドするとき


# 状況１） サブクラスにイニシャライザのオーバーライドを強制するとき

## Designated -> Designated の場合

![required_d2d.png](https://qiita-image-store.s3.amazonaws.com/0/46434/bc5b724c-ad33-06bc-e99e-87cdb4f5b25d.png)

```swift
class Animal {
    let name: String

    //
    // A（サブクラスにイニシャライザのオーバーライドを強制するときは、required 修飾子を付ける）
    //    
    required init() {
        self.name = "unknown"
    }
}

class Cat: Animal {
    //
    // A をオーバーライド（override 修飾子ではなく、required 修飾子を使うことに注意）
    //
    required init() {
        super.init()
    }
}
```

サブクラスにイニシャライザのオーバーライドを強制するときは、required 修飾子を使います。

```swift:上記コードを一部抜粋
    //
    // A（サブクラスにこのイニシャライザのオーバーライドを強制するときは、required 修飾子を付ける）
    //    
    required init() {
        self.name = "unknown"
    }
```

また、required 修飾子の付いたスーパクラスのイニシャライザをオーバーライドするときにも、required 修飾子を使います。

この場合には、override 修飾子ではなく、required 修飾子を使うことに注意してください。

```swift:上記コードを一部抜粋
    //
    // A をオーバーライド（override 修飾子ではなく、required 修飾子を使うことに注意）
    //
    required init() {
        super.init()
    }
```

### 補足１） override 修飾子ではなく、required 修飾子を使う理由

上記で override 修飾子を使えないのは、サブクラスのサブクラスにイニシャライザのオーバーライドを強制するためではないかと思われます。

```swift
class Animal {
    let name: String
    
    //
    // A
    //
    required init() {
        self.name = "unknown"
    }
}

class Cat: Animal {
    //
    // A'（A をオーバーライド。ここに required 修飾子がないと、サブクラス PersianCat に、このイニシャライザのオーバーライドを強制できない）
    //
    required init() {
        super.init()
    }
}

class PersianCat: Cat {
    //
    // A' をオーバーライド
    //
    required init() {
        super.init()
    }
}
```

### 補足２） インスタンスメソッドでは、required 修飾子を使用できない 

required 修飾子はイニシャライザでしか使えません。インスタンスメソッドでは使用できません。

```swift
class Animal {
    required func makeSound() { // -> error: 'required' may only be used on 'init' declarations
    }
}
```


## Designated -> Convenience の場合

![required_d2c.png](https://qiita-image-store.s3.amazonaws.com/0/46434/69826a0a-79bd-51a8-7016-ffcdb070c9c5.png)

```swift
class Animal {
    let name: String
    
    //
    // A
    //
    init(name: String) {
        self.name = name
    }
    
    //
    // B
    //
    required convenience init() {
        self.init(name: "unknown")
    }
}

class Cat: Animal {
    //
    // B をオーバーライド
    //
    required init() {
        //
        // A を呼び出す
        //
        super.init(name: "unknown")
    }
}
```

## Convenience -> Designated の場合

![required_c2d.png](https://qiita-image-store.s3.amazonaws.com/0/46434/b7ef72af-a510-de3b-1899-422464f23a4b.png)

```swift
class Animal {
    let name: String
    
    //
    // A
    //
    init() {
        self.name = "unknown"
    }
    
    //
    // B
    //
    required init(name: String) {
        self.name = name
    }
}

class Cat: Animal {
    //
    // B をオーバーライド
    //
    required convenience init(name: String) {
        //
        // スーパークラスから自動的に継承された A を呼び出す（下記の「注意１」「注意２」を参照）
        //
        self.init()
    }
}
```

### 注意１）

```self.init()``` では、スーパークラスから自動的に継承されたイニシャライザを呼び出しています。

詳細は、以下の記事を参照してください。

* [[Swift] クラスのイニシャライザ３： Designated Initializer と Convenience Initializer](http://qiita.com/cotrpepe/items/3052d91468f1b852582a) の「9. イニシャライザの自動的な継承」


### 注意２） 

オーバーライドをしている場合でも、convenience initializer の中では、スーパークラスのイニシャライザを呼び出せないことに注意してください。

詳細は、以下の記事を参照してください。

* [[Swift] クラスのイニシャライザ３： Designated Initializer と Convenience Initializer](http://qiita.com/cotrpepe/items/3052d91468f1b852582a) の「6. Convenience Initializer は同じクラスのイニシャライザを呼び出すことができる」


## Convenience -> Convenience の場合

![required_c2c.png](https://qiita-image-store.s3.amazonaws.com/0/46434/270086a6-f4ea-abc8-c753-d6cd17c9846f.png)

```swift
class Animal {
    let name: String
    
    //
    // A
    //
    init(name: String) {
        self.name = name
    }
    
    //
    // B
    //
    required convenience init() {
        self.init(name: "unknown")
    }
}

class Cat: Animal {
    //
    // B をオーバーライド
    //
    required convenience init() {
        //
        // スーパークラスから自動的に継承された A を呼び出す（上記の「注意１」「注意２」を参照）
        //
        self.init(name: "unknown")
    }
}
```


# 状況２） プロトコルのイニシャライザをオーバーライドするとき

## Designated -> プロトコルのイニシャライザの場合

![required_d2protocol.png](https://qiita-image-store.s3.amazonaws.com/0/46434/8407d339-3387-866c-1e8e-90b6cc234ab2.png)

```swift
protocol SomeProtocol {
    //
    // A
    //
    init()
}

class Animal: SomeProtocol {
    //
    // A をオーバーライド
    //
    required init() {
    }
}
```

プロトコルのイニシャライザには、required 修飾子は不要です。

```swift:上記コードを一部抜粋
protocol SomeProtocol {
    //
    // A
    //
    init()
}
```

一方で、プロトコルのイニシャライザをオーバーライドするときは、required 修飾子が必要です。

```swift:上記コードを一部抜粋
class Animal: SomeProtocol {
    //
    // A をオーバーライド
    //
    required init() {
    }
}
```

### 補足） プロトコルでは、Convenience Initializer を宣言できない

プロトコルでは、convenience initializer を宣言できないことに注意してください。

```swift
protocol SomeProtocol {
    convenience init() // ->  error: convenience initializer not allowed in non-class type
}
```


## Convenience -> プロトコルのイニシャライザの場合

![required_c2protocol.png](https://qiita-image-store.s3.amazonaws.com/0/46434/7604ba7f-9cde-5c7c-6550-e87604073b09.png)

```swift
protocol SomeProtocol {
    //
    // A
    //
    init(name: String)
}

class Animal: SomeProtocol {
    init() {
    }
    
    //
    // A をオーバーライド
    //
    required convenience init(name: String) {
        self.init()
    }
}
```


## 補足１） final クラスの場合は、required 修飾子はあってもなくてもいい

```swift
protocol SomeProtocol {
    //
    // A
    //
    init()
}

final class Animal: SomeProtocol {
    //
    // A をオーバーライド（required 修飾子はあってもなくてもいい）
    //
    init() {
    }
}
```

final クラスの場合は、required 修飾子はあってもなくてもかまいません（サブクラスにそのイニシャライザのオーバーライドを強制する必要がないため）。

一方で、final クラスでない場合は、required 修飾子が必要です（サブクラスにそのイニシャライザのオーバーライドを強制する必要があるため）。

```swift:finalクラスでない場合
protocol SomeProtocol {
    //
    // A
    //
    init()
}

class Animal: SomeProtocol {
    //
    // A'（A をオーバーライド。ここに required 修飾子がないと、サブクラス Cat に、このイニシャライザのオーバーライドを強制できない）
    //
    required init() {
    }
}

class Cat: Animal {
    //
    // A' をオーバーライド
    //
    required init() {
    }
}
```

## 補足２） インスタンスメソッドの場合は、required 修飾子は不要

```swift
protocol AnimalProtocol {
    //
    // A
    //
    func makeSound()
}

class Cat: AnimalProtocol {
    //
    // A をオーバーライド（required 修飾子は不要）
    //
    func makeSound() {
        println("Mew")
    }
}
```


## 補足３） override 修飾子と required 修飾子の両方が必要な場合

スーパークラスとプロトコルのイニシャライザを同時にオーバーライドする場合は、override 修飾子と required 修飾子の両方を付ける必要があります。

```swift
protocol SomeProtocol {
    init()
}

class Animal {
    init() {
    }
}

class Cat: Animal, SomeProtocol {
    //
    // 1. プロトコルのイニシャライザをオーバーライドしているので、required 修飾子が必要
    // 2. スーパークラスのイニシャライザもオーバーライドしているので、override 修飾子も必要
    //
    required override init() {
    }
}
```

override 修飾子と required 修飾子は逆でもかまいません。

```swift:上記コードを一部抜粋の上、一部改変
class Cat: Animal, SomeProtocol {
    //
    // override 修飾子と required 修飾子は逆でもかまわない
    //
    override required init() {
    }
}
```

# 参考文献

[The Swift Programming Language](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-XID_306)