Objective-C 継承,スーパークラス,サブクラス,オーバライド 【初級編 第8回】
Objective-C 継承,スーパークラス,サブクラス,オーバライド 【初級編 第8回】
ここまでクラスの作成などを行ってきましたが、そのクラスの定義のときに書いてる構文を思い出してください。
「@interface クラス名:スーパクラス」のところですね。クラスを作成するときはあるクラスを継承しますと
いいました。そこで今回はその継承について説明したいと思います。
あるクラスがあったとします。このクラスに存在している機能を利用しつつ、このクラスの機能に何か付け加えたい場合などに
新しいクラスを作成しもう一度インスタンス変数やメソッドを定義するのは2度手間です。
かといって元のクラスに直接機能を付け加えるようなことをしてしまうとそのクラスを使用している他のコードにも
影響が出るかもしれません。
そこで既存のクラスの機能を引き継ぎつつ、新しいクラスを定義する概念として継承というものがあります。
この継承を利用することで、もともとのクラスが持っていた機能を使用できる上に、新たにインスタンス変数やメソッドを
追加することができるため、また最初から新しいクラスを作って同じ動作をするメソッドやインスタンス変数などを
定義していく必要がありません。
このとき、基となるクラスの方を親クラスとかスーパークラスとか言います。実際のコードでは、
前回でてきていた[super init]としてあるsuperというのが親クラスを示しています。
そして継承してできたクラスの方が子クラスとかサブクラスといわれます。
継承すればスーパークラスのメソッドが使用できます。なので前回のコードでいえば、initメソッドをPersonクラスで
定義していなくても問題ありません。
試しに前回のコードのPersonクラスで実装されている(Person.mの中)initメソッドを全部コメントアウトしても
問題なく動きます。親クラスであるObjectクラスの方に実装があるからですね。とはいえ、エラーがでないだけで
前回言ったようにPersonクラスのインスタンスメソッドは初期化されません。
ではいろんなものが継承できるのかというとそうではありません。Objective-Cの場合は、スーパークラスは一つと決まっています。
いろんなスーパークラスを継承するクラスは作成できません。
例えばObjectクラス、MyTextクラス、TestClassクラスを継承したいということで以下のようなクラス定義を
することは無理ということです。
MyClass.h
@interface MyClass:Object,MyText,TestClass・・・
ただし、スーパークラスのさらにスーパークラスが存在するというのは問題ありません。
例えば Objectクラスを継承したPersonをさらに継承したStudentを作成しそれをさらに継承するということは
可能です。
Person.h
@interface Person:Object
Student.h
@interface Student:Person
CollegeStudent.h
@interface CollegeStudent:Student
イメージとしてはこんな感じ。ちょっと中にメソッドとかをいれました。
こういう場合、スーパークラスのさらにスーパークラスにあるメソッドはサブクラスから使用可能となります。
上の図にもあるようにPersonにあるメソッドはCollegeStudentクラスをオブジェクト化して使用する分には、CollegeStudentで
実装していなくても使用することができます。前回作成した「initWithWeight:height」は継承したほかのクラスでも
使えるということになります。直接的なサブクラスでなくても使用できます。
こうしてあるクラスを継承してさらにそのクラスを継承するいったことしていった場合、スーパークラスを遡っていくと
必ずあるクラスになります。それがルートクラスといわれるものです。このクラスは基本的なオブジェクトとしてのふるまいを
定義してあるクラスとなります。よってすべてのクラスはこのルートクラスを継承していないといけません。
gccの場合、Objectクラスがこのルートクラスに当たります。
なのでその2記事でも書きましたが、特に継承するものがない場合、このObjectクラスを継承することになります。
つまりObjectクラスで定義されているものは他のクラスで使用できるということですね。
実装する際に注意する点としては、他のクラスを継承するならそのクラスが定義されているヘッダーファイルを
インポートしておかなければならないということでしょうか。
例えばColleageStudent.hファイルではStudent.hをインポートする必要があるということです。
オーバーライド
前回のコードでもでてきたオーバライドに関しても少し述べておきます。
initというのはインスタンスの初期化用のメソッドとしてObjectクラスに用意されています。
しかしPerson.mの方でもinitメソッドを用意していました。
前回述べたようにObjectクラスのinitはこのクラスから作成されたオブジェクトを初期化するもので、
PersonのinitはPersonクラスのオブジェクトを初期化するものであるため、同じinitというメッセージ式でも行われることは
異なるわけです。
イメージとしてはこんな感じでしょうか。
こういったサブクラス側でスーパークラスで実装されているメソッドを少し拡張したいというようなときに使われます。
別のメソッド名にしてもかまいませんが、initPersonとやるよりは統一されたinitとやるほうが
メソッド数が少なくて済みます。(コードが減るわけではないです)
クラスを利用する側(メッセージを送信する側ですね)からすると、あるオブジェクトに対してinitと送信すれば
初期化ができるということになっていれば、初期化の呼び出し方法をいくつも覚えておく必要がなくなります。
今回のまとめとしては
- 継承することによって既存のクラスのインスタンス変数、メソッドを引き継いだクラスを作成できる
- 継承される側がスーパークラス、親クラスといわれ、継承した側がサブクラス、子クラスといわれる
- 複数のクラスを一気に継承する(多重継承)はできないが、スーパークラスのスーパークラスが存在するのはかまわない
- スーパークラスで実装されているものは、階層関係にあるサブクラスであれば使用可能である
- すべてのクラスはルートクラスが基となっている
- 実装の際はスーパークラスを定義しているヘッダーファイルをインポートする必要がある
- オーバーライドという処理の上書き機能により既存のメソッドを拡張できる
- メソッドがオーバライドされていれば、その上書きされた方の処理が呼び出され、オーバライドされていなければ
スーパークラスの処理が呼び出される
といったところでしょうか。
エンジニア転職・人材紹介サービス 【正社員】会員数150万人を誇る『@type』の企画・設計・運営/株式会社キャリアデザインセンター(二部上場) | |
エンジニア転職・人材紹介サービス【正社員】WEB開発エンジニア/株式会社インターエデュ・ドットコム |
未経験OKの仕事 | 上場企業の仕事 | 高待遇の仕事 | 外資系の仕事 | 社内SEで検索 | 自社サービスで検索