Objective-C2.0文法メモ クラス(その1)

Objective-CC言語オブジェクト指向の概念を取り入れた言語ですので、クラスを利用することができます。

クラスの定義(インターフェース部分)

interface−endで囲みます。
書式:MyClass.h

@interface MyClass : NSObject
{
    type field; // メンバ変数に相当する
}
-(returnType) method:(argType)arg;    // メンバ関数に相当する
@end

クラスの実装

implementation-endで囲みます。
例:MyClass.m

#import "MyClass.h"
@implementation MyClass
- (id)init
{
    self = [super init];
    if (self) {
       // initialization
    }
    return self;
}
-(returnType) method:(argType)arg
{
    // statement
}
@end
オブジェクトの生成・解放

生成したら解放しておきます。メモリ管理の仕組みは後述予定。

    MyClass* object = [[MyClass alloc] init];
    [object release]
インスタンスへのメッセージ送信(メソッド呼び出し)
    ret = [object method: arg];
実装例

基本的なクラスの実装例です。
privateなメンバとしてage(年齢)を持ち、セッターをsetAge、ゲッターをageとしてみます。他にsleepというメソッドを持っているとします。(注)getterはメンバと同じ名前である必要があります。

Cat
-age:int
+setAge(val:int):void
+age():int
+sleep(hours :int):void

     △(汎化)

NSObject
Cat.h
#import <Foundation/Foundation.h>

/**
 * class declaration
 */
@interface Cat : NSObject
{
    int age;
}
/**
 * setter
 */
-(void) setAge:(int)age_;
/**
 * getter
 */
-(int) age;
/**
 * example method
 */
-(void) sleep:(int)hours;
@end

Catクラスですが、NSObjectクラスの派生クラスとして実装します。NSObjectクラスを利用するためにFoundation.hをインクルードしておきます。

Cat.m
#import "Cat.h"

// class implementation
@implementation Cat
// initialization
- (id)init
{
    self = [super init];
    if (self) {
        // initialize
    }
    return self;
}
// setter
-(void)setAge:(int)age_
{
    age = age_;
}
// getter
-(int)age
{
    return age;
}
// example method
-(void) sleep:(int) hours
{
    NSLog(@"Cat says: I sleep %d hours", hours);
}
@end

クラスを利用する側の実装です。
main.m

#import "Cat.h"
int main (int argc, const char * argv[])
{
    //  インスタンス生成
    Cat* mike = [[Cat alloc] init];
    [mike setAge: 2];
    [mike sleep: 16];
    //  インスタンス解放
    [mike release];
    return 0;
}

メソッドキーワード

メソッドを定義するときにはまず先頭に戻り値型を記述して、後は"キーワード:(引数型)引数名"を繰り返して記述します。

// 宣言
-(returnType) methodKeyword1: (argType1)argument1
			Keyword2:(argType2)argument2
			Keyword3:(argType3)argument3
// 利用
[object methodKeyword1:value1 Keyword2:value2 Keyword3:value3];

コンパイラ側ではキーワードの組み合わせに対してメソッドが同一かどうかを判断しています。
C++では型と変数名だけ定義するだけで、実際に利用するときには何の値を渡しているのかが分かりにくいのですが、Objective-Cでは呼び出すときもキーワードを必ず明記しなければいけないので、渡しているデータの種類が一目瞭然になります。

-(int) setX: (int)x
		Y:(int)y
		Z:(int)z;

[point setX:10 Y:20 Z:30];

さらに、キーワードを工夫してメソッドを利用するときにより文章に近い名称にすることによって、可読性を高めることができます。
// キーワードを工夫した例

-(int) setAge: (int)age_
		AndSize:(int)size_
		AndName:(NSString*) name_;

[object setAge:10 AndSize 20 AndName @"mike"];
-(int) : insertElement:(Element*)element
		WithID:(int)id
		WithSorting:(bool) isSort;

[queue insertElement:root WithID:-1 WithSorting:false ];

イニシャライザ

オブジェクト生成時の初期化処理はNSObjectクラスのinitを利用します。

-(id) init;

戻り値はid型で全てのオブジェクトを参照することができます。キーワードを増やして引数付きのイニシャライザ(C++でいうコンストラクタ)を定義・実装することもできます。

// 宣言
-(id) initWithAge:(int)age_
               size:(int)size_;
// 実装
-(id) initWithAge:(int)age_
               size:(int)size_
{
    self = [super init];
    if (self) {
        age = age_;
        size = size_;
    }
    return self;
}

メンバへのアクセス

"->"演算子を利用すれば各メンバに直接アクセスできます。

    Cat* mike = [[Cat alloc] init];
    [mike setAge: 2];
    NSLog(@"age = %d", mike->age);

※ドット演算子→プロパティへアクセスするための演算子ですのでここでは省略→後述

アクセス制御

C++Javaなどと同様にpublic, protected, privateによって分類できます。

@interface Sample : NSObject
{
@public
    int publicMember;
@private
    int privateMember;
@protected
    int protectedMember;
}
@end

@implementation Sample
// initialization
- (id)init
{
    return [super init];
}
@end
Sample* sample = [[Sample alloc]init];
NSLog(@"%d",sample->publicMember);
NSLog(@"%d",sample->privateMember);      //  error:Instance variable 'privateMember' is private
NSLog(@"%d",sample->protectedMember);  //  error:Instance variable 'protectedMember' is protected
[sample release];

静的メンバ

静的メソッド

先頭を"+"にするとクラスレベルでアクセス可能なメソッドになります。

静的フィールド

Objective-Cでは直接静的変数を定義することはできません。変数と同じ名前の静的なgetterを定義しておいて、実装側で静的変数に書き込むように実装すれば、あたかも静的フィールドを使っているかのように利用することができます。

実装例

Sample.h

@interface Sample : NSObject
{
}
+(int) staticField;
+(void) staticMethod;
@end

Sample.m

static int s_staticField = 1;

@implementation Sample
// initialization
- (id)init
{
    return [super init];
}
+(int) staticField{
	return s_staticField;
}
+(void) staticMethod{
	NSLog(@"static method was called");
}
@end

main.m

    //  静的メソッドを呼び出す
    [Sample staticMethod];
    //  静的変数を取得する
    NSLog(@"staticField = %d",[Sample staticField]);

デストラク

デストラクタに対応するものとしてNSObjectにdeallocというメソッドが用意されています。終了時にメモリを解放しないといけない場合はこのメソッドを利用します。

-(void) dealloc;