Skip to content

Swift_inheritance

kobayashiharuto edited this page Jul 31, 2021 · 3 revisions

継承

クラスをちょっと変えて作り直す。そんなお話。


無駄な気がする実装

「うーん... Person クラス作ったはいいものの、挨拶が異なる Ninja クラスが作りたいなぁ」

「でも、挨拶以外は Person クラスと一緒だし、下みたいに全部実装し直すのなんか無駄だなぁ」

class Person {
    var name: string
    
    init(name: string) {
        self.name = name
    }
    
    func greet() {
        print("こんにちは。私は\(self.name)です。")
    }
    
    func dance() {
        print("ダンス!")
    }
}

class Ninja {
    var name: string
    
    init(name: string) {
        self.name = name
    }
    
    func greet() {
        print("ドーモ。\(self.name)です。")
    }
    
    func dance() {
        print("ダンス!")
    }
}

そうですね。無駄です。

プログラマの三大美徳として、「怠惰」「短気」「傲慢」というのがあげられます。
つまり、コーディングするときは怠惰にならなくてはいけません。
使いまわせるのに同じものを書き直す?やってはいけません。


継承で使いまわそう!

こんな時は継承です!
継承って言葉通り、クラスのメソッドやプロパティを引き継いで使うことができます。

class クラス名: 継承元クラス名 で継承できます。
そして、メソッドに override をつけることで、親クラス(継承元のクラス)のメソッドを変更したものを実装できます!

class Ninja: Person {
    // メソッドを上書きしましょう!
    override func greet() {
        print("ドーモ。\(self.name)です。")
    }
}

ninja = Ninja(name: 'ダークニンジャ')
ninja.greet()  		// ドーモ。ダークニンジャです。
ninja.dance()  		// ダンス! (もちろん親クラスのメソッドが引き継がれてるので使えます)
print(ninja.name)	// ダークニンジャ(プロパティも引き継がれています)

これで、クラスの一部を引き継いで、使いまわせるようになりました!
継承元を 親クラス or スーパークラス と呼び、継承先を 子クラス or サブクラス と呼びます。


子クラス特有のメソッドやプロパティを追加しよう

普通に追加できます。特に語ることもないですね。

class Ninja: Person {
    ver target = "小林"
    
    override func greet() {
        print("ドーモ。\(self.target)=サン。\(self.name)です。")
    }
    
    func kill() {
        print("KILL!")
    }
}

ninja = Ninja(name: 'ダークニンジャ')
ninja.greet()  		// ドーモ。小林=サン。ダークニンジャです。
ninja.kill()		// KILL!

親クラスのメソッドを使おう

super.親クラスのメソッド名 とすると、親クラスのメソッドを呼び出せます。
また、イニシャライザは override を書かずとも上書きされます。
その場合は super.init() で親クラスのイニシャライザを呼び出してあげましょう。

class Ninja: Person {
    
    init(name: String) {
        super.init(name: name)
        print("ニンジャ 見参") 	// インスタンス化した際に見参させよう。
    }
    
    override func greet() {
        print("ドーモ。\(self.target)=サン。\(self.name)です。")
        super.dance() // アイサツしたときダンスもさせてみよう。
    }
    
    func kill() {
        print("KILL!")
    }
}

ninja = Ninja(name: 'ダークニンジャ') 	// ニンジャ 見参
ninja.greet()  						// ドーモ。小林=サン。ダークニンジャです。ダンス!

型が一緒とみなされる

なんと、子クラスは親クラスの型と同じとみなされます。
例えば、以下のような Person クラスしか入れられない関数に入れることが可能になります!
つまり、既存の関数も使いまわせるってわけ!便利~

func greetTogether(person: Person) {
    person.greet()
    print("こんにちは、\(person.name)さん。")
}

var person = Person(name: "小林")
var ninja = Ninja(name: "ダークニンジャ")

greetTogether(person)	// こんにちは。私は小林です。 こんにちは、小林さん。 
greetTogether(ninja)	// ドーモ。ダークニンジャです。 こんにちは、ダークニンジャさん。

まとめ

  • 継承により、親クラスの実装を使いまわせる
  • しかも、一部を変えられるので多様な子クラスを作れる
  • さらに、親クラスの型としてみなされるので、関数も使いまわせる!
Clone this wiki locally