Objective-Cの第五歩 クラスの継承とメソッドのオーバーライド
公開日:
:
iOSアプリを書く! C言語, Objective-C, Xcode, オブジェクト指向
前回Objective-Cの第四歩では、等差数列の和を計算するプログラムGaussTesterの作成を通じてメソッドの実装方法などを説明した。今回は、作成したクラスを継承して新たなクラスを作成する方法と、親クラスのメソッドと同名メソッドを用意して、メソッドのオーバーライドをする方法を説明する。
クラスに1人くらいは賢いヤツがいる
GaussTesterは、その名の通り数学者ガウスが小学校の授業で等差数列の和を計算させられたとき一瞬で解いたというエピソードを元にしている。和を求めるStudentクラスのsummary0ToXメソッドだが、ガウスであればStudent.mにおける実装のように、forループで回して各項を足していくといった処理は行わないだろう。
そこで、最初に名前をたずねて、名前が”Gauss”であったら、等差数列の和を求める公式を使って合計を出すというように、処理を変えてみよう。
クラスの継承
新しいクラスGaussを作成したいのだが、Studentクラスと同じように名前のプロパティを持ち、イニシャライザを実装し…という処理をいちいち書くと、重複になってしまう。生徒GaussはStudentという大括りに含まれることは確かなので、こういう場合はStudentクラスを継承してGaussクラスを作成するという方法をとる。
Xcodeから新規ファイルを選択して、例の如くObjective-C Classを作成するのだが、名前を入力する画面のSubclass of:というメニューの値をStudentにする。
すると、作成されたファイルのうちGauss.hで自動的にStudent.h継承のための記述をしてくれる。勿論、継承元のクラスの.hクラスを読み込んで、通常の新規クラス作成でNSObjectを継承している部分を継承元クラスの名称に変えるだけなので、Xcodeの助けを借りずに自分で書き込んでも手間ではないだろう。
#import "Student.h" @interface Gauss : Student @end |
一方、Gauss.mの中の記述は以下のようになっている。
#import "Gauss.h" @implementation Gauss @end |
こちらはNSObjectを直接継承した場合と特に変わりなし。
この状態で、GaussTesterのmain.mの中でStudent.hをimportしている行を消して、代わりにGauss.hを読み込むようにする。また、Studentクラスのインスタンスをalloc,initWithNameメッセージを使って作成している部分を、Gaussクラスに置き換えてみる。そのようにしてプロジェクトを実行してみても、問題なく動くはずだ。これはStudentクラスを継承して何も追加しない状態のGaussクラスが、親クラスのStudentクラスと同じメソッド・プロパティを持ち、同じ振る舞いをするからである。
親クラスのメソッドのオーバーライド
Studentクラスを継承して作成したGaussクラスに、独自のプロパティやメソッドを追加することも出来る。勿論、追加したプロパティ・メソッドはGaussクラスで呼ぶことが出来、親クラスのStudentクラスには追加されない。
このように、大元のNSObjectクラスを頂点として、子クラスでより具体的なプロパティ・メソッドを追加していくといった連鎖があって、Objective-Cのクラス群ができているわけだ。オブジェクトの基本的な振る舞いであるallocメソッドやinitメソッドは、継承連鎖の頂点のNSObjectで定義されたものを引っ張ってきているわけで、連鎖の途中でいじらない限りは、同じ振る舞いが保証されるというわけである。
では、連鎖の途中でいじる場合はどうなるか…ということだが、それがメソッドのオーバーライドとなる。
メソッドのオーバライドは、子クラスの中で親クラスの同名メソッドを再定義する形で行われる。では、Gaussクラスにsummary0ToXメソッドを書いて、Studentクラスの同名メソッドを置き換えてみよう。
まず、Gauss.hの記述。
#import "Student.h" @interface Gauss : Student - (int)summary0ToX:(int)x withGap:(int)gap; @end |
続いて、Gauss.mで実際の処理を書く。
#import "Gauss.h" @implementation Gauss - (int)summary0ToX:(int)x withGap:(int)gap{ int sum=0; sum = (x + x%gap)*(x/gap + 1)/2; return sum; } @end |
あとはmain.mの中で、生徒名を聞いてインスタンス作成する箇所に分岐を作ればOK。
#import <Foundation/Foundation.h> #import "Student.h" #import "Gauss.h" int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... char name[100]; int target,gap; Student* studentA; printf("どの学生に答えさせますか?\n"); scanf("%99s",name); if(strcmp(name,"Gauss") == 0){ studentA = [[Gauss alloc] initWithName:[NSString stringWithUTF8String:name]]; } else { studentA = [[Student alloc] initWithName:[NSString stringWithUTF8String:name]]; } printf("0からどの数字まで計算させますか?\n"); scanf("%d",&target); studentA.numberTarget = target; printf("数字間の差は?\n"); scanf("%d",&gap); studentA.numberGap = gap; [studentA sayAnswer]; } return 0; } |
今回の場合、継承元のStudentクラスもGaussクラスもどちらもインスタンス化される可能性があるので、両方の.hファイルを忘れずにインポートするのを忘れずに。
以上がクラスの継承と親クラスのメソッドのオーバーライドになる。次回か次々回あたりから、いよいよiOSアプリケーションの作成に入っていく予定。
関連記事
-
Objective-Cの第三歩 クラスとクラスメソッドを定義する
Swiftの事をひとまず置いておいてObjective-Cの入門編を書いているわけだが、前々回の"H
-
Objective-Cの第四歩 インスタンスプロパティ・メソッドを定義する
Objective-Cの第三歩では、ピュアC言語からのObjective-Cのクラス入門ということで
-
Objective-CでiOSアプリの第二歩 とにかく立ち上がればというレベルのHello, World!アプリを作成
前回はiOSアプリ作成の第一歩として、Empty Applicationを選択した際に書いてあるコー
-
iOSプログラミング入門書では、まず最初のHello, World!すら難しい
Hello, World!が第一歩 新しくプログラミング言語を習得するときに、「この言語でのH
-
Objective-Cの第一歩(仕切り直し)
前回Objective-Cの第一歩として挙げたコードであるが、綺麗さっぱり忘れてほしい。というのは、
-
Objective-CでiOSアプリの第三歩 UIViewControllerの必要性を理解する
前回はUIViewControllerの存在を無視して"Hello, World!"アプリケーション
-
Xcode 6の正式リリースまでに、Objective-Cでアプリを一つ仕上げる!
Swiftに早速触れてみたい!でもXcode 6がベータ版の間は、有料(7800円/年)のDevel
-
Objective-CでiOSアプリの第一歩 新規プロジェクトで生成されるコードの解説
しけたコンソールアプリばかり作っていたけれど、ようやっとiOSプログラミングに入るとしよう。急がない
-
Objective-Cでは何故.hファイルと.mファイルを作成させられるのか
前回説明したように、Objective-Cでプログラムを書く際には、別にC言語そのもののつもりで書い
-
Objective-Cの第六歩 プロトコルの宣言と実装
Objective-Cの第五歩では、親クラスの継承とメソッドのオーバーライドについて説明した。そこま