はじめに
この記事では、override 修飾子について説明します。
他の記事へのリンク
- [Swift] クラスのイニシャライザ1: イニシャライザの引数の書き方
 - [Swift] クラスのイニシャライザ2: プロパティの初期化方法
 - [Swift] クラスのイニシャライザ3: Designated Initializer と Convenience Initializer
 - [Swift] クラスのイニシャライザ4: override 修飾子
 - [Swift] クラスのイニシャライザ5: required 修飾子
 - [Swift] クラスのイニシャライザ6: Failable Initializer
 
環境
- Xcode 6.1 (Playground)
 
1. override 修飾子とは?
override 修飾子は、
- スーパークラスのイニシャライザをサブクラスのイニシャライザでオーバーライドするとき
 
に使います。
class Animal {
    let name: String
    
    //
    // A
    //
    init(name: String) {
        self.name = name
    }
}
class Cat: Animal {
    //
    // スーパークラスの A をオーバーライドする
    //
    override init(name: String) {
        super.init(name: name + "!!")
    }
}
var c = Cat(name: "kitty")
println(c.name) // -> kitty!!
2. override 修飾子の書き方
2.1. Designated initializer の場合
override init() {
    ...
}
2.2. Convenience initializer の場合
override convenience init() {
    ...
}
3. オーバーライドができる条件
オーバーライドできるのは、以下の2つの条件が満たされている場合のみです。
- 条件1) スーパークラスとサブクラスのイニシャライザが「同じイニシャライザ」である
 - 条件2) オーバーライドされる側が designated initializer である
 
条件1) スーパークラスとサブクラスのイニシャライザが「同じイニシャライザ」である
「同じイニシャライザ」とは、「引数の型、数、名前が同じ」という意味です。引数名も同一である必要があるので注意しください。
例えば、以下の A と B のイニシャライザは、引数の型と数が同じですが、第一引数の名前が異なっています(name と nickname)。そのため、「同じイニシャライザ」ではないので、オーバーライドできません。
A
class Animal {
    init(name: String, age: Int) {
        ...
    }
}
B
class Cat: Animal {
    init(nickname: String, age: Int) {
        ...
    }
}
条件2) オーバーライドされる側が designated initializer である
例1) Designated -> Designated の場合
class Animal {
    var name: String
    
    //
    // A
    //
    init() {
        self.name = "unknown"
    }
}
class Cat: Animal {
    //
    // A をオーバーライド -> OK
    //
    override init() {
        super.init()
        self.name = "kitty"
    }
}
var c = Cat()
println(c.name) // -> kityy
例2) Convenience -> Designated の場合
class Animal {
    var name: String
    
    //
    // A
    //
    init() {
        self.name = "unknown"
    }
}
class Cat: Animal {
    //
    // A をオーバーライド -> OK
    //
    override convenience init() {
        //
        // スーパークラスから自動的に継承された A を呼び出す(下記の「注意1」「注意2」を参照)
        //
        self.init()
        self.name = "kitty"
    }
}
var c = Cat()
println(c.name) // -> kityy
注意1)
self.init() では、スーパークラスから自動的に継承されたイニシャライザを呼び出しています。
詳細は、以下の記事を参照してください。
- [Swift] クラスのイニシャライザ3: Designated Initializer と Convenience Initializer の「9. イニシャライザの自動的な継承」
 
注意2)
オーバーライドをしている場合でも、convenience initializer の中では、スーパークラスのイニシャライザを呼び出せないことに注意してください。
詳細は、以下の記事を参照してください。
- [Swift] クラスのイニシャライザ3: Designated Initializer と Convenience Initializer の「6. Convenience Initializer は同じクラスのイニシャライザを呼び出すことができる」
 
例3) Designated -> Convenience の場合
class Animal {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    //
    // A
    //
    convenience init() {
        self.init(name: "unknown")
    }
}
class Cat: Animal {
    //
    // A をオーバーライド -> NG
    //
    override init() { // ->  error: initializer does not override a designated initializer from its superclass
    }
}
例4) Cesignated -> Convenience の場合
class Animal {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    //
    // A
    //
    convenience init() {
        self.init(name: "unknown")
    }
}
class Cat: Animal {
    //
    // A をオーバーライド -> NG
    //
    override convenience init() { // ->  error: initializer does not override a designated initializer from its superclass
        self.init(name: "unknown!!")
    }
}
4. 例
例1) スーパークラスに Default Initializer があるパターン
class Animal {
    var name: String = "unknown"
    
    //
    // 全てのプロパティにデフォルト値が設定されているので、
    // default initializer "init() {}" が暗黙的に実装される
    //
}
class Cat: Animal {
    //
    // スーパークラスの default initializer をオーバーライド
    //
    override init() {
        super.init()
        self.name = "kitty"
    }
}
var c = Cat()
println(c.name) // -> kitty
例2) スーパークラスにイニシャライザが自動的に継承されているパターン
class Animal {
    var name: String
    
    //
    // A
    //
    init(name: String) {
        self.name = name
    }
}
class Cat: Animal {
    //
    // Designated initializer が1つも実装されていないので、
    // スーパークラス Animal から A が自動的に継承される(下記の「補足」を参照)
    //
}
class PersianCat: Cat {
    //
    // A をオーバーライド
    //
    override init(name: String) {
        super.init(name: name)
    }
}
var c = Cat(name: "kitty")
println(c.name) // -> kityy
補足)
イニシャライザの自動的な継承については、以下の記事を参照してください。
- [Swift] クラスのイニシャライザ3: Designated Initializer と Convenience Initializer の「9. イニシャライザの自動的な継承」
 



