page_adsence

2014年2月6日木曜日

Objective-Cのクラス周りの書き方

Objective-Cの勉強を始めたものの、今までPHPやJSしかやってこなかった自分にとってはとても分かりにくい書き方だった。
演算子とか条件分岐やループ処理といった部分に関しては、今までやってきた言語同様の書き方だったが、クラス関連の書き方が全然違ったので激しく違和感を感じるとともに、慣れていないので非常に書きづらい。
忘れそうなので、ここにまとめておく。

ファイル構造
ヘッダファイル及び実装ファイルのファイル内の構造は以下の通り。

ヘッダファイルのファイル構造
#import <フレームワーク/ファイル>
#import ソースファイル

@interface クラス名;スーパークラス名 <プロトコル>
{
    インスタンス変数宣言;
}
プロパティ宣言;
メソッド宣言;
@end

実装ファイルのファイル構造
#import ヘッダファイル

@interface クラス名() <プロトコル>
{
    インスタンス変数宣言;
}
プロパティ宣言;
メソッドの定義;
@end

@implementation クラス名
メソッド定義;
@end

クラスの宣言
  • クラス宣言は必ず必要
  • クラス宣言はヘッダファイル(XXX.h)に記載する
  • 親クラスは必ず指定しておく(継承すべき親クラスがない場合はNSObjectクラスを指定)
※継承すべき親クラスがない場合にNSObjectクラスを指定する理由は、オブジェクトのしての振る舞いをするために必要な機能がこのクラスに書かれているため。
そのため、用意されている全てのクラスはこのNSObjectクラスが基底クラスとなっている。

書き方
@interface クラス名:親クラス{
    インスタンス変数の定義
}

メソッドの定義

@end

インスタンス変数のスコープの種類 Objective-Cのスコープの種類は以下の3種類で、他の言語と同様。
スコープを省略した場合は自動的にprotectedになる。
  • @private 宣言したクラス内からのみアクセス可能
  • @protected 宣言したクラス内及び継承されたサブクラスからアクセス可能(デフォルト)
  • @public どこからでもアクセス可能

クラスメソッドとインスタンスメソッドの書き分け
  • +から書き出した場合はクラスメソッド
  • -から書きだした場合はインスタンスメソッド
クラスメソッドの書き方
+(返り値のデータ型)メソッド名
クラスメソッドの書き方(引数あり)
+(返り値のデータ型)メソッド名:(引数1のデータ型)引数1 ラベル2:(引数2のデータ型)引数2 ・・・

インスタンスメソッドは先頭の+を-に変更するだけなので省略。
ここまでが主にヘッダファイルに記載する内容。

以下は簡単なサンプル
@interface myClass:NSObject {
    NSInteger aaa; //自動的にprotectedとなる
    @private NSString *bbb;
    @protected BOOL isTrue;
    @public NSString *ddd;
}

+(void)myClassMethod;
-(void)myInstanceMethod;
@end



クラスの実装
  • クラスの実装は必ず実装ファイル(XXX.m)に書く

書き方
#import "クラス名.h";

@implementation クラス名
    ヘッダファイルで宣言したメソッドの実装コード
@end

以下は簡単なサンプル
#import myClass.h;

@implementation myClass

+(void)myClassMethod
{
    NSLog(@"myClassMethod");
}

-(void)myInstanceMethod
{
    NSLog(@"myInstanceMethod");
}

@end



クラスのインスタンス化及び初期化
  • クラスのインスタンス化を行った後に初期化をする。
  • インスタンス化にはNSObjectに定義されているallocメソッドを使う。
  • 初期化にはNSObjectに定義されているinitメソッドを使う。
書き方
変数 = [[クラス名 alloc]init];

以下は簡単なサンプル
MyClass *myClass = [[myClass alloc]init];

以上がクラスの基本的な書き方や使い方。
以下は書いてて気持ち悪かった部分。

クラスメソッドを実行したい場合
[オブジェクト メソッド名];

例)
[myClass myfunc];


クラスメソッドを実行したい場合(引数が1つ)
[オブジェクト メソッド名:引数];

例)
[myObj myfunc:a];


クラスメソッドを実行したい場合(引数が複数)
[オブジェクト メソッド名:引数1 ラベル2:引数2 ラベル3:引数3・・・];

例)
[myObj myfunc:a label2:b label3:c];

※尚、ここに記載されているのはクラスメソッドを実行したい場合で、インスタンスメソッドを実行する場合はインスタンス化して初期化してから下記の書き方でメソッドを実行して下さい。

この書き方だが、メッセージ式の書き方らしい。
[〜]の間で1つのメッセージとして判断される。
1つ納得いかない点は引数の1つ目のラベルがメソッド名になってしまう点だ。
なんか気持ち悪いけど慣れていくしかないか・・・。