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

継承

クラス間の継承を実現するには、インターフェースの宣言に以下のように記述します。

@interface SubClass : SuperClass

基底クラスAnimalと、それを継承したCatクラスを作成してみます。
Animal.h

#import <Foundation/Foundation.h>

@interface Animal : NSObject
{
    int age;
}
-(void) setAge:(int)age_;
-(void) greet;
@end

Animal.m

#import "Animal.h"

@implementation Animal
- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
    }
 
    return self;
}
-(void) setAge:(int)age_
{
    age = age_;
}
-(int) age
{
    return age;
}
-(void) greet
{
    NSLog(@"hello!");
}
@end

Cat.h

#import "Animal.h"
@interface Cat : Animal
{
    NSString* name;
}
-(void) setName:(NSString*)name_ Age:(int)age_;
-(void) greet;
@end

Cat.m

#import "Cat.h"

@implementation Cat
- (id)init
{
    return [super init];
}
-(void)setName:(NSString*)name_ Age:(int)age_
{
    name = name_;
    [super setAge:age_];
}
-(void) greet
{
    NSLog(@"mew!");
}
@end

オーバーライド

上記派生クラスのgreetメソッドは基底クラスの同じメソッドをオーバーライドしています。派生クラスを参照して実行すると実際に派生クラスのメソッドが実行されています。
main.m

    Cat* mike = [[Cat alloc]init];
    [mike greet];
    [mike release];

実行結果

mew!

superとself

派生クラス内で基底クラスのメソッドを実行するには、Javaなどと同様に"super"を利用します。

    [super method];

また、現在のインスタンスへの参照を取得するにはselfを利用します。

    [self method];

多態性

Catクラスに加えてAnimalクラスから派生したDogクラスを追加してみます。

Dog.h

#import "Animal.h"
@interface Dog : Animal
{
    NSString* name;
}
-(void) setName:(NSString*)name_ Age:(int)age_;
-(void) greet;
@end

Dog.m

#import "Dog.h"

@implementation Dog
- (id)init
{
    return [super init];
}
-(void)setName:(NSString*)name_ Age:(int)age_
{
    name = name_;
    [super setAge:age_];
}
-(void) greet
{
    NSLog(@"bowwow!");
}
@end

基底クラスの参照を用いて、別の派生クラスのメソッドを呼び分けることができます。

    Cat* mike = [[Cat alloc]init];
    Dog* jack = [[Dog alloc]init];    

    Animal* pet = mike;
    [pet greet];
    pet = jack;
    [pet greet];
    
    [mike release];
    [jack release];

実行結果

mew!
bowwow!

プロパティの利用

クラスのメンバにアクセスするために通常setter, getterを準備しますが、これらをひとまとめにしてメンバにアクセスできる仕組みをプロパティと呼びます。Objective-C2.0以降ではこのプロパティという概念を利用することができます。
プロパティを定義するにはインターフェース部分に以下のように記述します。

@property (mode) type memberName;

さらに実装部分で"synthesize"を定義しておきます。

@synthesize memberName;
実装例

Song.h

#import <Foundation/Foundation.h>
@interface Song : NSObject
{
    enum Genre{
        POPS,
        ROCK,
        JAZZ
    };
    enum Genre genre;
}
@property (readwrite) enum Genre genre;
@end

Song.m

#import "Song.h"

@implementation Song
- (id)init
{
    return [super init];
}
@synthesize genre;
@end
メンバへのアクセス

プロパティを定義したあと、メンバにアクセスするには"."(ドット)演算子を利用します。Songオブジェクトのgenreにアクセスした例です。

    Song *song = [[Song alloc]init];
    song.genre = POPS;
    NSLog(@"genre id = %d[s]", song.genre);
    [song release];

※retain, readonly, nonatomicについて追記するかもしれません