(1)構造体を使う理由、malloc、freeを使う理由
(2)Objective-C言語を使う理由 その1
(3)Objective-C言語を使う理由 その2
(4)Objective-C言語を使う理由 その3
パート2:Objective-C言語によるオブジェクト指向プログラミング
それでは実際にObjective-C言語を使ったオブジェクト指向プログラミングを学習しましょう。
最初におこなうのは、パート1で作った構造体を使ったC版オブジェクト、Item、FileItem、FolderItem、BundleItemのObjective-C版作成です。
アプリケーションとしての機能はまったく同じものを、Objective-Cを使ったオブジェクト指向プログラミングでおこなうとどうなるかを体験してください。
Objective-Cを使う新規プロジェクト作成
まずはObjective-Cを使う新規プロジェクトを作成します。
Xcodeを起動してFile→New→Project…メニューを選んでください。
現れたテンプレート選択画面で、OS X ApplicationのCommand Line Tool テンプレートを選んで新規プロジェクトを作成するところまではC版と一緒です。

Objective-Cを使う準備は、次ぎのオプション画面でTypeにFundationを指定することで整います。
プロジェクト名はoc-folderとしました。

Nextボタンをクリックしたら、次に出てくるプロジェクト保存先設定画面では保存先をデスクトップ、Source ControlはMy Macを選択しチェックし、Createボタンをクリックします。
注意)Source Controlはソースの変更を履歴として残す機能です。今回の学習とは直接関係ないのでチェックしなくても支障はありません。またプロジェクト保存先もデスクトップである必要はありません。

Createボタンをクリックすると新しいワークスペースウィンドウが表示されます。
------------
サンプル:03-00-oc-folder.zip
プロジェクトにはmain.cのかわりにmain.mが加わっていて、内容もmain.cとは少し異なることがわかると思います。

Objective-C用のソースファイルには拡張子 .mが使われます。

とりあえず、そのままRunさせてみてください。
次のようにコンソールにHello, World!が表示されます。


Hello, World!に加えて日付などが出力されているのは、main関数でprintfの代わりにNSLog関数を使っているからです。
Objective-CはCの拡張なので、main関数がアプリケーションの入り口になる点に違いはありません。
違いはCに加えてObjective-Cでの記述ができる点です。
NSLog関数の他#importや@autoreleasepool { }といったキーワードも初めて登場しますが、これらはObjective-C特有のものです。
サンプル:03-00-oc-folder main.m
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!"); ←printfの代わりにNSLogが使われている
}
return 0;
}
#import
#importは#includeに多重読み込み防止機能を追加したものです。
例えば、次のような記述は、同一ソース内での多重読み込み防止のためのものでした。
サンプル:02-04-folder Item.h
#ifndef folder_Item_h ← 定義されていれば#endifまで無視される
#define folder_Item_h ← ここで定義
・・・
#endif
こうすることで、間違ってItem.hを2回#includeしてしまっても問題がなくなります。
#include "Item.h"
#include "Item.h" ← folder_Item_hの定義によって、2回目の#includeは実質無効になる
#importは、この多重読み込み防止をコンパイラ側に担当させるものです。
そのため#importでしか利用されないヘッダーファイルは、先の#ifndef~#endifの記述が不要となります。
@autoreleasepool { } (オートリリースプールブロック)
@autoreleasepool { }はオブジェクトの生成、破棄に関係する記述です。
次回以降に説明しますがObjective-Cではオブジェクトの生成・破棄を、構造体の生成・破棄で使ったmalloc、freeとは異なる方法で管理します。今はその有効範囲の設定とだけ解釈してください。
@autoreleasepool { から } の間に生成されたオブジェクトに効果をおよぼすので、通常、main関数の開始直後から終了までの間を囲うように記述します。

NSLog関数
NSLog関数はロギング(活動記録)用の関数です。
printf同様、可変引数であり、第1引数には出力形式を整えるための文字列("%d"や"%f"なども指定可能)を受け取るようになっていて、渡された引数に日時等の付加情報を加えてコンソールに出力します。
第1引数には文字列オブジェクトを渡す必要があります。
@"Hello, World!"(文字列オブジェクト)
NSLog関数の第1引数に渡している事からわかるように@"Hello, World!"が文字列オブジェクトです。
ただし通常のオブジェクトとは作成方法が異なり、リテラル構文によって作られたオブジェクトです。リテラル構文については次回以降に説明します。
Objective-Cにおけるオブジェクト
前回までは、Cでオブジェクト指向プログラミングを実現するために構造体を使いました。

オブジェクト指向プログラミングの特徴
オブジェクトの振る舞いはオブジェクト自身が決める
派生オブジェクトは派生元の特性を引き継ぐ
まずは、このうちのItem構造体とFileItem構造体をObjective-Cのオブジェクトとして定義してみましょう。
クラス
Cでtypedef struct {…}を使って新しい構造体を定義したように、Objective-Cでは
@interface … @end
@implementation … @end
という2つのブロックで新しいオブジェクトを定義します。
@interfaceブロックでは主にオブジェクトの派生関係やオブジェクトが内部に持つ変数などを宣言し、@implementationブロックではオブジェクトの振る舞いを定義します。
そして、このようにオブジェクトの構造や特性を定義することをクラスを定義するといいます。
2つのブロックはクラス名によって関係付けられます。クラス名をどんなものにするかは任意です。
例えばItemとして振る舞うオブジェクトの定義をItemクラスとするなら次のようになります。

この仕組みによって、クラス別に振る舞いを定義する事が可能となり、Cでおこなっていた構造体の関数ポインタへの関連関数の結びつけといった作業が不要となります。
サンプル:02-04-folder FileItem.c 前回おこなった構造体の関数ポインタへの関連関数の結びつけ作業
Item* FileItemAlloc()
{
if (file_super == NULL)
file_super = ItemAlloc();
Item* item = malloc(sizeof(Item));
*item = *file_super;
item->print = printFileItem;
return item;
}
「Objective-Cでプログラミング その2」へ続く
