2013年7月12日金曜日

Objective-Cの勉強(2);メソッドの宣言



メソッドの宣言



メソッドは以下の書式で宣言する。
関数のプロトタイプ宣言に近い。Objective-Cでは関数名から引数のラベル名までを含め全体を「メッセージ」と呼ぶ。
 
 -(リターン型)メソッド名:(引数型)引数;                       // 1引数の場合
 -(リターン型)メソッド名:(引数型)引数1 label2:(引数型)引数2; // 2引数の場合
 -(リターン型)メソッド名:(引数型)引数,...;                   // 可変引数の場合

リターン型は必ず()で括る。なぜかというと、Objective-Cの基本型はintではなくid型というものになっているからである。要するに、この()はid型からの型キャストを示しているのである。事実id型なら()も要らないし、省略も出来る。しない方が良いけど。

id型はクラスに対し、動的に(=実行時に確定される)型や内容を変更することが出来る万能型。int等基本型の代わりにはできないけど。
idの本性は、オブジェクトのアドレスを示すポインターである。typedefで*を含めて名称定義してあるようなので、*は省略する。


引数の区切りは「:」であり「,」ではない。「,」は可変引数を示すからであるが、可変引数はあまり使われない。Apple提供のクラスでも、それほど多くは出てこない。
Objective-Cでは、同名メソッドを引数別に定義出来るため、必要性が少ないのだろう。
可変引数の取り出し型は、Cと同じくva_listとva_start()を使う。


2引数以上の場合、引数名にラベルを付けるのが「習慣」だそうな。ラベルはその直後の変数の物。すなわち、Objective-Cではメソッド名は第1引数のラベル、その後各引数にラベルを付けるということだ。ラベルなのでラベル名と:に間にスペースを入れてはいけない。
Objective-CはCからの拡張実装であるから、すでにそれが持っているラベル認識機能をうまく使った実装であると言えよう。
(実はラベルは省略可能だが「推奨されていない」。)


ラベル名を変えると、同じメソッド名でも異なるメッセージとして扱われる。
これはオーバーライドとはちょっと違い、メッセージの受信オブジェクトの変更になる。


メソッドはメンバー変数名と同じであってもかまわない。通常メンバー変数は外部から直アクセスさせることはないかららしい。
ただ、初心者は分けた方が迷わなくて良いかもしれない。



ラベル名はCの予約語名とは同じでも大丈夫だが、#define定数名と同じではいけない。
プリプロセッサの方が先にソースを通すためである。


1つのメソッドで複数の引数が同じラベル名を持っていても良いようである。
NSObjectには-(id)performSelector: withObject: withObject:というメソッドが存在したりする。
が、あんまり使うべきじゃないのでは、と思ったりする。



先頭の「-」はインスタンスへのメソッドであることを示す。
他に「+」というのもあって、これはクラスに対するメソッドであることを示す。
インスタンスメソッドは実体を持ったオブジェクトに対して実行される関数であり、クラスメソッドはクラスに実体を持たせる時に実行させる関数、もしくはクラスの特性をして持っておくべくメソッドと理解すればいい。


インスタンスメソッドはselfおよびメンバー変数にアクセスできるが、クラスメソッドはそれがアクセスできない。当然コンパイルするとエラーが出る。
クラスメソッドはクラスを実体化=インスタンス化するときなど、インスタンスがない状態でも呼び出されるからである。



init=初期化されていない/またはalloc=確保されていないクラス内のメソッドを呼び出すとどうなるか。
実は何も起こらない。エラーも何も発生せずに素通りしてしまう。Objective-Cでは初期化してしていないクラスはnilであり、nilへの呼び出しは全て無視するようになっているからである。
もし実装したはずのメソッドが実行されないときは、そのインスタンスが正しく初期化されているか確認すべきである。



0 件のコメント:

コメントを投稿