Objective-C 継承関係を利用したメソッドの呼び出し.
前回、継承の基本的な概念について解説しました。そして、サブクラスでスーパークラスのメソッドを上書きした場合でも、上書きされたスーパークラスのメソッドへアクセスできるという話をしました。
今回はそこの部分の話と、その機能を利用したメソッドの拡張の話をしたいと思います。
スーパークラスのメソッドの呼び出し
スーパークラスへのメッセージの送信は「super」を用い、以下のように書きます。
「 [super メソッド名]; 」
次の図では、クラスBがクラスAのサブクラスで、method1とmethod3を上書きしています。この時、method1でスーパークラスのmethod3を呼び出したいとき、「 [ self method3 ]; 」と呼び出してしまうと、自分の新しいmethod3が呼び出されます。selfはクラスBの自分自身を指すからです。そこで図のように、「 [ super method3 ]; 」とsuperを使って呼び出すと、スーパークラスのmethod3を呼び出すことができます。
クラスBのmethod1でスーパークラスのmethod3を呼び出していますが、この後には、好きな処理を実装できます。つまり、この機能を用いれば、すべてを上書きせずに、スーパークラスのあるメソッドの機能を保持したまま、追加でそのメソッドに処理を付け加える事ができます。
次の図を見てみましょう。クラスCはクラスBを継承し、method2を上書きしています。method2の定義はクラスBにありませんので、クラスAのメソッドを上書きしていることになります。
プログラムを書いていると、スーパークラスの処理を保持したまま、新たに機能を付け加えたいという場面が多々あります。そのようなとき、クラスCのmethod2のような書き方をすれば、まずスーパークラスのmethod2の呼び出しをしてから、新たに独自のメソッドを書き加えることができます。言うならば、スーパークラスのmethod2を拡張していることになります。
この機能を用いれば、効率よくクラスの継承を用いたプログラミングをしていくことができます。
イニシャライザを読み解く
今回解説している、スーパークラスのメソッドを呼び出す機能ですが、もうすでに何度も僕のブログの中でも出てきています(”インスタンス変数へアクセスする”)。それがイニシャライザです。
今までイニシャライザは以下のように書いていました。
-(id) init { if( (self = [super init]) ) { /*イニシャライズの処理*/ } return self; }
ここで「super」というのが出てきています。今まで、説明を省いていましたが、この部分も同じようにスーパークラスのメソッドの呼び出しに当たります。ここでスーパークラスのイニシャライザを呼びですことで、スーパークラスで定義されているインスタンスのの初期化処理などを引き継ぐことができます。そして、サブクラス独自の初期化処理は、スーパークラスの初期化が行われてから行います。
このようにクラスを継承するとき、初期化時にスーパークラスのイニシャライザを呼び出すようにしておけば、スーパークラスはもう一つ上の階層のクラスのイニシャライザを呼び出しているので、数珠つなぎにルートクラス(NSObject)まで初期化が行われていきます。
スーパークラスの呼び出しをif文に入れるのは、スーパークラスのイニシャライズが失敗した時のためです。スーパークラスの初期化が失敗したときは、このselfにnil(空のオブジェクト)が入り、このクラスの初期化もnilをreturnで返します。よってこれ以降の継承クラスでも初期化は行われません。安全に継承関係を組み立てるためにこのような方法が取られています。
スーパークラスの初期化が終わった後は、if文の中で自由にそのクラス独自の初期化処理を実装します。通常はインスタンス変数に値を定義したりします。
少し複雑になって来ましたので、一旦ここで切ります。
次回はもう少し複雑なメソッドの呼び出しとイニシャライズの関係を見ていきます。