Objective-C クラスの継承における、メソッドの複雑な呼び出し.
自分のメソッドへアクセスする、”self”変数の使い方
前回、「super」を使ってスーパークラスのメソッドを呼び出す方法を紹介しました。これと同様に「self」変数を用いれば自分のメソッドへアクセスすることができます。
「 [ self (メソッド名)]; 」
しかし、この方法を用いてメソッドを呼び出す際には、注意しなければならない点があります。次の図を見てください。
今、クラスAを継承したクラスBと、クラスBを継承したクラスCを想定します。また、クラスBはmethod1とmethod3を上書きし、クラスCはmethod2を上書きしています。
クラスBのmethod3の中身は、先ほどの”self”変数を用いて自身のmethod1とmethod2を呼び出しています。
クラスBからインスタンスを生成し、このインスタンスが①のようにmethod3を実行したとすると、まずmethod3はself変数を用いて、②のように自分のmethod1を呼び出します。
その後method2を呼びだそうとしますが、自分にはその定義が無いので、スーパークラスのmethod2を③のように呼び出します。
では次のようなケースではどのようにプログラムは処理されるのでしょうか。
クラスCから生成したインスタンスが①のようにmethod3を実行したとします。method3はクラスCで上書きされてないので、定義がありません。したがって、スーパークラスのクラスBのmethod3を実行します。
ここでmethod3はselfを用いてmethod1を呼び出していますが、ここでのselfは決してクラスBではありません。selfは自分自身、つまりクラスCのインスタンスを指しているのです。
元々はクラスBのmethod1を意図していたはずですが、ここでプログラムはまず②のようにクラスCのmethod1を見に行きます。
幸運にもクラスCにはmethod1の定義が書かれていないので、もう一度スーパークラス、すなわちクラスBのmethod1に戻ってきています。
そしてmethod2を今度は呼び出しています。この場合はどうでしょうか。ここでもselfを使って呼び出していますので、プログラムはクラスCインスタンスのmethod2だと思い込み、③のように呼び出します。そして、今度はmethod2の定義を発見するので、クラスCのmethod2を実行します。
クラスBのmethod2を意図していたはずが、クラスCのmethod2に起き変わってしまっています。
これは他のメソッドを定義し直すしか回避する方法がありません。このように継承関係の中で、selfやsuperを用いた呼び出しをする場合は、注意しないと予期せぬ動作を起こす可能性があります。