連載
» 2008年10月08日 00時00分 公開

Cocoaの素、Objective-Cを知ろう(2):一番初めのObjective-Cプログラム (2/3)

[竹下肯己,株式会社 qnote]

クラスを宣言するヘッダファイル

 まずは「Song」と「Singer」の2つのクラスの宣言部分を作成します。

a
a


b
c

d
d

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

// Songクラスの宣言
@interface Song : NSObject {
  NSString *lyrics;
}
- (NSString *)lyrics;
- (void)setLyrics:(NSString *)argLyrics;
@end
Song.h

a
a
a


b
c

d
d

#import <Foundation/NSObject.h>
#import <stdio.h>
#import "Song.h"

// Singerクラスの宣言
@interface Singer : NSObject {
  Song *song;
}
- (void)setSong:(Song *)argSong;
- (void)sing;
@end
Singer.h

 クラスの詳細な定義方法に関しては、連載の別の回で詳しく解説します。ここでは、クラスを定義するうえで最低限必要となる要素のみ説明します。

a. 関連ファイルの読み込み

 まず、ファイルの先頭で関連クラスのヘッダファイルをimportしています。これは先ほど解説したとおり、そのクラスで必要となる別のクラスのヘッダファイルをコンパイル前に読み込むように指示するものです。なお、Singer.hでimportしているstdio.hは、C言語の基本ライブラリヘッダファイルの1つで、ここではコンソールへの文字出力を行うためにimportしています。

b. クラス名とスーパークラス名の宣言

 クラスの宣言は、すでに述べたようにコンパイラディレクティブの中に記述します。「@interface」から「@end」までが、クラスのインターフェイス宣言のためのコンパイラディレクティブです。

 クラス名は、@interfaceに続けてクラス名 : スーパークラス名のように記述します。スーパークラスというのは、そのクラスの親となる既存のクラスのことで、これを指定するとスーパークラスの機能や属性の多くを引き継ぐ(継承する)ことができます。引き継いだ側のクラス(子となるクラス)はサブクラスと呼ばれます。

 Objective-Cでは、ほとんどのクラスで必須となる汎用的な機能を保持するNSObjectというクラスが、Foundationフレームワークの中に用意されています。通常、あらゆるクラスがこのNSObjectクラスの直接または間接的なサブクラスとして定義されるため、NSObjectクラスはルートクラスとも呼ばれます。

c. メンバ変数の宣言

 クラス名とスーパークラス名に続く、{}で囲まれたブロックの中には、クラスのメンバとなる変数を宣言します。サンプルでは、Songクラスは文字列を表現するNSStringというクラス型(このクラスもFoundationフレームワークの中に用意されています)の変数をメンバとして宣言しています。Singerクラスでは、前出のSongクラス型の変数を宣言しています。

 クラス型の変数は、いわゆるポインタとして宣言する必要があります。ポインタは、クラスの実体が保存されているメモリ上のアドレスを表す変数で、変数名の前に「*」(アスタリスク)を付けて宣言します。クラス型の変数が常にポインタであることで、プログラム内での変数の受け渡し時に、常に同じ実体を指し示すことができるのです。

d. メソッドの宣言

 変数の宣言ブロックに続いて、メソッドの宣言を記述します。ここでは宣言のみ行うので、記述するのはメソッド名と戻り値、引数などだけです。

 Objective-Cにおけるメソッドの記述方法は独特で、この言語の大きな特徴の1つとなっているため、詳しくは後々の回で解説します。サンプルの例に沿って簡単に説明しておくと、先頭の「-」(マイナス記号)に続く()内には、メソッドの戻り値の型(戻り値がない場合はvoid)を示し、続いてメソッド名を記述します。引数がある場合には、続けて「:」(コロン)、引数の型(これも()内に記述)、引数名のように記述します。

クラスを実装するファイル

 続いて、クラスを実装します。

e


f
g
g
g
g
g
g
#import "Song.h"

// Songクラスの実装
@implementation Song : NSObject
- (NSString *)lyrics{
  return lyrics;
}
- (void)setLyrics:(NSString *)argLyrics {
  lyrics = argLyrics;
}
@end
Song.m

e


f
g
g
g
g
g
g
g
g
#import "Singer.h"

// Singerクラスの実装
@implementation Singer : NSObject
- (void)setSong:(Song *)argSong {
  song = argSong;
}
- (void)sing{
  printf(
    "♪ %s ♪ \n",
    [[song lyrics] UTF8String]);
}
@end
Singer.m

e. 対応するヘッダファイルの読み込み

 先の図にも示してあるとおり、クラスの実装ファイルは、対応するヘッダファイル(クラスのインターフェイス宣言部分)をimportする必要があります。

f. クラス名とスーパークラス名

 クラスの実装も、やはりコンパイラディレクティブの中に記述します。「@implementation」から「@end」までが、クラスの実装を記述するためのコンパイラディレクティブです。

 クラス名の記述については、クラスの宣言の場合と同じです(Song.hとSinger.hのコード中のbおよび対応する解説を参照してください)。

g. メソッドの実装

 続いてメソッドの処理内容を実装します。メソッド名や戻り値、引数などの記述方法は、クラス宣言ファイル内のメソッド宣言部分と同じになります(Song.hとSinger.hのコード中のdおよび対応する解説を参照してください)。

 メソッドの処理内容の記述は通常のプログラムロジックとなりますが、前回も述べたようにクラスのオブジェクトに対しメッセージを送るという、Objective-C独特の(Smalltalkの影響による)記述が登場します。

 SongクラスのlyricsメソッドやsetLyricsメソッド、およびSingerクラスのsetSongメソッドは、単にクラスのメンバ変数の値を取得したり、新たに値をセットしたりするだけのものです。このようなメソッドを、変数に対するアクセサと呼びます。

 Singerクラスのsingメソッドでは、Songクラスが保持する歌詞の内容(文字列)に音符を付加して出力しています。UTF8StringはObjective-Cの文字列オブジェクト(NSString)からC言語の文字列を取得するメソッドです。NSStringクラスが持つ豊富な機能については、別の回で詳しく解説します。

正しくメッセージを伝えよう

 クラスの定義ができたら、それらのクラスを利用して処理を実行させる実行プログラムを作成します。これはプログラムのエントリポイントとなりますので、C言語のmain関数に記述します。

h
h




i
i

j


j





#import "Song.h"
#import "Singer.h""

// 実行プログラム
int main(void) {

  id song;
  id singer;

  song = [[Song alloc] init];
  [song setLyrics:@"La La La ..."];

  singer = [[Singer alloc] init];
  [singer setSong:song];
  [singer sing];

  return 0;
}
main.m

h. 関連ファイルの読み込み

 ここでは、SongおよびSingerの2つのクラスを組み合わせた処理をしますので、2つのヘッダファイルを読み込んでおきます。

i. id型の変数を用意

 クラスのオブジェクトを保存するために、汎用的な型であるid型の変数を用意します。id型の場合、「*」(アスタリスク)でポインタであることを明示する必要はありません。

j. クラスのインスタンスを作成

 クラスの実体(インスタンス)を作成しています。多くのオブジェクト指向型の言語では、「singer = new Singer();」などと記述する方式が一般的ですが、Objective-Cでは、インスタンス生成や初期化のメソッドを、メッセージ式を利用して呼び出します。

 allocinitは、ここではクラスの実体を生成して初期化するための定番メソッドとだけ理解しておいてください。両メソッドとも、ルートクラスであるNSObjectに定義されていますので、自作のクラスで独自に定義していなくても利用することができます。

 メッセージ式は、サンプルコードのように入れ子にして実行することができます。コードの例では、SongクラスやSingerクラスに対してallocメソッドを実行するようメッセージを送り、さらにその戻り値であるクラスの実体に対してinitメソッドを実行するようにメッセージを送っています。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。