Edited at

[Swift] クラスのイニシャライザ4: override 修飾子

More than 3 years have passed since last update.


はじめに

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


他の記事へのリンク


環境


  • 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() では、スーパークラスから自動的に継承されたイニシャライザを呼び出しています。

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


注意2)

オーバーライドをしている場合でも、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


補足)

イニシャライザの自動的な継承については、以下の記事を参照してください。


参考文献

The Swift Programming Language