Objective-C入門 Mac OSX編
- はじめに
- 動作環境
- 対象者
- Objective-Cとは?
- 環境構築
- 最終目的
- コメント
- コーディング規約
- 基本構造
- ハローワールド
- データ形式
- 演算子
- 配列
- I/O
- 制御構造
- 分岐
- 反復
- API
- クラス
- クラスの初期化と解放
- アクセス権限( Access Privilege )
- クラス変数・クラスメソッド
- 継承(Inheritance)
- ポリモーフィズム(Polymorphism)
- クラスオブジェクト
- オーバーライド(Overide)
- オーバーロード(Oveload)
- インタフェース
- セレクタ
- カテゴリ
- その他
- デバック
- 最後に
- 参考資料
Objective-Cとは?
Objective-Cは、Smalltalkを基礎とした非常に動的な言語です。コンパイラはオブジェクト自体について多くの情報を実行時まで決めずにおきます。 C++,Javaはある程度コンパイル時に型を確定します。
手続き型言語の代表的なC言語は、データを構造体というデータ型でひと纏めることで データの抽象化を実現しています。関数はライブラリとして再利用可能です。ライブラリを利用するユーザは関数の名前(インタフェース)が必要なため 実装を隠蔽することが可能です。このように手続き型言語では、最も抽象化してもデータ(状態)とそれに対する演算(操作)を区別することまでしか出来ません。
オブジェクト指向言語は、更に状態と操作を区別している事を隠蔽し、1つの単位とします。 またプログラム言語はデータと関数間のやりとりは完全に切り離す事ができないため、構造化言語は特に固有のデータ構造への依存度が高いです。これにより再利用性の難しさが上げられます。
Objective-Cは、C++,Javaの静的型定義ではなく、Smalltalkと同様に動的型定義です。これはクラス定義を実行時まで引き伸ばします。 そのため、動的バインディングが可能になっています。動的バインディングとは、呼び出すメソッドを実行時に決定する事です。C++,Javaでも 似たような機能を実装できますが、コンパイル時にある程度の型が確定しているため、その型に依存する事になります。このようなバインディングを 遅延バインディングと呼びます。動的ロードも可能です。これはプログラム実行中にプログラムの追加が可能なことを意味します。
環境構築
どうにかしてXcodeをインストールしてください。
最終目的
NSライブラリをつかったバイナリクロックの作成。
コメント
// 一行のコメント
/* 複数行のコメント */
コーディング規約
分かりません。Apple社のプログラムなどはコーディング規約があるでしょう。Java[TM]言語コーディング規約と似たような規約を採用することが多いと思います。言い方をかえるとこの規約はObjective-Cなど先代からのオブジェクト指向を参考にしているともいえます。
基本構造
ヘッダファイル(hello.h)にインタフェースを書きます。これはC言語のヘッダと同様で実装を隠蔽します。 また、hello.mに実装を記述します。
#import文でヘッダファイルを読み込みます。#includeとは異なり#define文を書かなくても重複してヘッダを読み込むことはありません。
@interfaceディレクティブでインタフェースを書きます。
:セミコロンで継承を記述します。
-記号がインスタンスメソッドを意味します。+記号がスタティックメソッドを意味します。
~/develop/obc satoshiokita$ cat hello.h
#import <stdio.h>
#import <objc/Object.h>
@interface TestClass : Object
- (void) getMessage;
@end
hello.mに必要な実装を記述します。
@implementationで実装します。
@"string"という書き方では、NSString型になります。
[]でメソッドを呼びます。
id型は、java.lang.Objectのように抽象型です。
~/develop/obc satoshiokita$ cat hello.m
#import "hello.h"
#import "Foundation/NSString.h"
@implementation TestClass
- (void) getMessage {
NSString *tmp = @"Hello Mac OSX Objective-C world\n";
printf("", [ tmp cString ]);
}
@end
int main(int argc, char *argv[]) {
id obj = [ TestClass alloc ];
[ obj getMessage ];
return 0;
}
~/develop/obc satoshiokita$ gcc -o hello hello.m -lobjc -framework foundation
~/develop/obc satoshiokita$ ./hello
Hello Mac OSX Objective-C world
Foundation/NSString.hでヘッダを読み込みます。では、どこから読み込むのでしょう。gcc -vオプションで確認できます。
~/develop/obc satoshiokita$ gcc -v -o hello hello.m -lobjc -framework foundation Reading specs from /usr/libexec/gcc/darwin/ppc/3.3/specs Thread model: posix gcc version 3.3 20030304 (Apple Computer, Inc. build 1666) /usr/libexec/gcc/darwin/ppc/3.3/cc1obj -quiet -v -D__GNUC__=3 -D__GNUC_MINOR__=3 -D__GNUC_PATCHLEVEL__=0 -D__APPLE_CC__=1666 -D__DYNAMIC__ hello.m -fPIC -quiet -dumpbase hello.m -auxbase hello -version -o /var/tmp//ccNyaUim.s GNU Objective-C version 3.3 20030304 (Apple Computer, Inc. build 1666) (ppc-darwin) compiled by GNU C version 3.3 20030304 (Apple Computer, Inc. build 1666). GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=131072 ignoring nonexistent directory "/usr/ppc-darwin/include" ignoring nonexistent directory "/Local/Library/Frameworks" #include "..." search starts here: #include <...> search starts here: /usr/local/include /usr/include/gcc/darwin/3.3 /usr/include End of search list. Framework search starts here: /System/Library/Frameworks /Library/Frameworks End of framework search list. /usr/libexec/gcc/darwin/ppc/as -arch ppc -o /var/tmp//cc0rzfsL.o /var/tmp//ccNyaUim.s ld -arch ppc -dynamic -o hello -lcrt1.o -lcrt2.o -L/usr/lib/gcc/darwin/3.3 -L/usr/lib/gcc/darwin -L/usr/libexec/gcc/darwin/ppc/3.3/../../.. /var/tmp//cc0rzfsL.o -lobjc -framework foundation -lgcc -lSystem | c++filt
gccのデフォルト設定で /System/Library/Frameworks, /Library/Frameworksディレクトリを確認することが上記から分かります。
また、NSStringクラスをリンケージするためには、-framework foundation オプションが必要になります。これはgccのApple用拡張です。ためしに-framework foundationオプションをはずしてみます。コンパイルはできますが、リンケージが出来ない為実行ファイルが作られません。
Reading specs from /usr/libexec/gcc/darwin/ppc/3.3/specs Thread model: posix gcc version 3.3 20030304 (Apple Computer, Inc. build 1666) /usr/libexec/gcc/darwin/ppc/3.3/cc1obj -quiet -v -D__GNUC__=3 -D__GNUC_MINOR__=3 -D__GNUC_PATCHLEVEL__=0 -D__APPLE_CC__=1666 -D__DYNAMIC__ hello.m -fPIC -quiet -dumpbase hello.m -auxbase hello -version -o /var/tmp//ccnlfN9A.s GNU Objective-C version 3.3 20030304 (Apple Computer, Inc. build 1666) (ppc-darwin) compiled by GNU C version 3.3 20030304 (Apple Computer, Inc. build 1666). GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=131072 ignoring nonexistent directory "/usr/ppc-darwin/include" ignoring nonexistent directory "/Local/Library/Frameworks" #include "..." search starts here: #include <...> search starts here: /usr/local/include /usr/include/gcc/darwin/3.3 /usr/include End of search list. Framework search starts here: /System/Library/Frameworks /Library/Frameworks End of framework search list. /usr/libexec/gcc/darwin/ppc/as -arch ppc -o /var/tmp//ccE2ZfRe.o /var/tmp//ccnlfN9A.s ld -arch ppc -dynamic -o hello -lcrt1.o -lcrt2.o -L/usr/lib/gcc/darwin/3.3 -L/usr/lib/gcc/darwin -L/usr/libexec/gcc/darwin/ppc/3.3/../../.. /var/tmp//ccE2ZfRe.o -lobjc -lgcc -lSystem | c++filt ld: Undefined symbols: .objc_class_name_NSConstantString __NSConstantStringClassReference
ハローワールド
~/develop/obc satoshiokita$ cat hello2.m
#import <stdio.h>
#import <objc/Object.h>
@interface HelloClass : Object
- (void) getMessage;
@end
@implementation HelloClass
- (void) getMessage {
printf("Hello Objective-C World\n");
}
@end
int main(int argc, char *argv[]) {
id obj = [ HelloClass alloc ];
[ obj getMessage ];
return 0;
}
~/develop/obc satoshiokita$ gcc -o hello2 hello2.m -lobjc -framework Foundation
~/develop/obc satoshiokita$ ./hello2
Hello Objective-C World
データ形式
objc/objc.hに定義されている。
| 型 | 定義 |
| id | データ構造体へのポインタ |
| Class | クラスデータ構造体へのポインタ |
| SEL | セレクタ。メソッド名を識別するためにつかう |
| IMP | idを戻すメソッド実装へのポインタ |
| BOOL | YES | NO (TRUE | FALSEではない) |
| nil | nullオブジェクトポインタ(id)0の定数 |
| Nil | nullクラスオブジェクトポインタ(class)0の定数 |
~/develop/obc satoshiokita$ cat hello3.m
#import <stdio.h>
#import <objc/Object.h>
#import <Foundation/NSString.h>
@interface NilTest : Object
- (void) getMessage;
@end
@implementation NilTest
- (void) getMessage {
printf("hoge\n");
}
@end
int main(int argc, char *argv[]) {
id hoge = Nil;
/* nil test */
if ( hoge == Nil ) {
printf("Nil type mean nill type in C language\n");
}
printf("0\n", hoge);
/* BOOL test */
BOOL aaa;
printf("0\n", aaa);
aaa = YES;
printf("0\n", aaa);
aaa = NO;
printf("0\n", aaa);
return 0;
}
~/develop/obc satoshiokita$ gcc -o hello3 hello3.m -lobjc -framework Foundation
~/develop/obc satoshiokita$ ./hello3
Nil type mean nill type in C language
0
0
1
0
演算子
基本はC言語と同様です。
配列
基本はC言語と同様です。
I/O
基本はC言語と同様です。
制御構造
基本はC言語と同様です。
分岐
基本はC言語と同様です。
反復
基本はC言語と同様です。
API
C言語の上位言語であるためC言語のライブラリをそのまま利用できます。またGNU拡張やApple拡張が存在します。この記事は文法の概要を説明しているため、詳しいことは省略します。
クラス
メソッドの前にマイナス記号をつけるとインスタンスメソッドになります。プラス記号をつけるとクラスメソッドになります。
[s-okita@stoc objc]$ cat class_test.m
#import <stdio.h>
#import <objc/Object.h>
@interface Person : Object
{
/* instance variable */
char *name;
int age;
}
/* instance method */
- (char*) getName;
- (int ) getAge;
- (void ) setData : (char *) name : (int) age;
@end
@implementation Person
- (char*) getName {
return name;
}
- (int ) getAge {
return age;
}
- (void ) setData : (char *) name : (int) age {
/* C++/Javaのthisキーワード */
self->name = name;
self->age = age;
}
@end
int main(int argc, char *argv[])
{
char *test_name = "satoshi";
/* []でメソッドを呼び出す方式をメッセージ方式と呼びます。
* これはSmalltalkの方式です。allocメソッドはC++/Javaのnewキーワード
* と同様。Objectクラスに実装されています。
*/
id obj = [ Person alloc ];
[ obj setData : test_name : 26 ];
printf("\n", [ obj getName ]);
printf("0\n", [ obj getAge ]);
return 0;
}
[s-okita@stoc objc]$ gcc -Wall -O2 -o class_test class_test.m -lobjc
class_test.m:1:2: warning: #import is obsolete, use an #ifndef wrapper in the header file
class_test.m: In function `-[Person setData::]':
class_test.m:27: warning: local declaration of `name' hides instance variable
class_test.m:28: warning: local declaration of `age' hides instance variable
[s-okita@stoc objc]$ ./class_test
satoshi
26
クラスの初期化と解放
クラスの初期化を多くの言語ではコンストラクタ、開放をデストラクタなどと呼びます。名称は異なれObjective-Cにも同様な機能が備わっています。
[s-okita@stoc objc]$ cat new_test.m
#include <stdio.h>
#include <objc/Object.h>
/* initializer sample */
@interface TestClass : Object
{
int a;
}
-(id)init;
@end
@implementation TestClass
-(id)init {
[super init];
a = 100;
printf("instanciate!!!\n");
return self;
}
-(id)free {
printf("destruct!!!\n");
return [super free];
}
@end
int main(int argc, char *argv[]) {
id obj = [ TestClass alloc ];
[ obj init ];
[ obj free ];
[ [ TestClass new ] free ];
return 0;
}
[s-okita@stoc objc]$ gcc -Wall -O2 -o new_test new_test.m -lobjc
[s-okita@stoc objc]$ ./new_test
instanciate!!!
destruct!!!
instanciate!!!
destruct!!!
アクセス権限( Access Privilege )
クラスに情報と処理を実装するとそれを公開するかしないかなどのアクセス権を実装できます。これによりカプセル化を実現します。
[s-okita@stoc objc]$ cat access_privilege.m
#import <stdio.h>
#import <objc/Object.h>
@interface SuperHoge : Object
{
/* default protect */
int defaultProtectedVal;
@public
int publicVal;
@private
int privateVal;
@protected
int protectedVal;
}
@end
@interface SubHoge : SuperHoge
-(id) init;
-(int) getProtectedVal;
@end
@implementation SuperHoge
@end
@implementation SubHoge
-(id) init {
[ super init ];
return self;
}
-(int) getProtectedVal {
return protectedVal;
}
@end
int main(int argc, char *argv[]) {
/* public access */
SuperHoge *obj = [ SuperHoge new ];
printf("0\n", obj->publicVal);
/* protected access */
SubHoge *obj2 = [ SubHoge new ];
/* printf("0\n", [ obj2 getProtectedVal ] ); */
printf("0\n", [ obj2 getProtectedVal ]);
return 0;
}
[s-okita@stoc objc]$ gcc -Wall -O2 -o access_privilege access_privilege.m -lobjc
access_privilege.m:1:2: warning: #import is obsolete, use an #ifndef wrapper in the header file
[s-okita@stoc objc]$ ./access_privilege
0
0
クラス変数・クラスメソッド
クラス変数は存在しません。C言語同様ヘッダファイルにglobal変数を定義します。
[s-okita@stoc cpp]$ cat static_test.m
#include <stdio.h>
#include <objc/Object.h>
int static_val = 0;
@interface TestClass : Object
+ (void) printHello;
+ (int) getCount;
+ (void) increment;
@end
@implementation TestClass
+ (void) printHello {
printf("hello\n");
}
+ (int) getCount {
return static_val;
}
+ (void) increment {
static_val++;
}
@end
int main(int argc, char *argv[]) {
[ TestClass printHello ];
[ TestClass increment ];
printf("0\n", [ TestClass getCount ]);
return 0;
}
[s-okita@stoc cpp]$ gcc -Wall -O2 -o static_test static_test.m -lobjc
[s-okita@stoc cpp]$ ./static_test
hello
1
継承(Inheritance)
CoffeeクラスがDrinkクラスを継承しているため、Drinkクラスのメソッドが利用できます。 C++と同様にコロン(:)記号で継承を表します。
[s-okita@stoc objc]$ cat inheritance_test.m
#import <stdio.h>
#import <objc/Object.h>
@interface Drink : Object
{
char * name;
}
- (void ) setName : (char *)name;
- (char*) getName;
@end
@interface Coffee : Drink
@end
@implementation Drink
- (void ) setName : (char *)name
{
self->name = name;
}
- (char*) getName
{
return name;
}
@end
@implementation Coffee
@end
int main(int argc, char *argv[]) {
id obj = [ Coffee alloc ];
[ obj setName : "java coffee" ];
printf("\n", [ obj getName ] );
return 0;
}
[s-okita@stoc objc]$ gcc -Wall -O2 -o inheritance_test inheritance_test.m -lobjc
inheritance_test.m:1:2: warning: #import is obsolete, use an #ifndef wrapper in the header file
inheritance_test.m: In function `-[Drink setName:]':
inheritance_test.m:18: warning: local declaration of `name' hides instance variable
[s-okita@stoc objc]$ ./inheritance_test java coffee
ポリモーフィズム(Polymorphism)
オブジェクト指向言語には、ポリモーフィズムを実現するための機能が備わっています。クラス、継承もそうですが、以下では実際にポリモーフィズムを実現している例を記述します。
クラスオブジェクト
個々のオブジェクトクラスには、Classクラスを保持しているためclassメソッドを呼び出すことができる。これを使えばメソッドのポリモーフィズムが実現できる。
[s-okita@stoc s-okita]$ cat ClassClass.m
#import <stdio.h>
#import <objc/Object.h>
/*
* Javaのjava.lang.Classと同じ機能
*/
@interface PolySuper : Object
+ (void) printMessage;
@end
@interface PolyTest : PolySuper
+ (void) printMessage;
@end
@interface PolyTest2 : PolySuper
+ (void) printMessage;
@end
@implementation PolySuper
+ (void) printMessage
{
printf("PolySuper");
}
@end
@implementation PolyTest
+ (void) printMessage
{
printf("PolyTest\n");
}
@end
@implementation PolyTest2
+ (void) printMessage
{
printf("PolyTest2\n");
}
@end
int main(int argc, char *argv[])
{
/* classメソッドでClassクラスを生成 */
Class classClass = NULL;
classClass = [ PolyTest class ];
/*メソッドのポリモーフィズム */
[ classClass printMessage ];
classClass = [ PolyTest2 class ];
[ classClass printMessage ];
return 0;
}
[s-okita@stoc s-okita]$ gcc -Wall -O2 -o ClassClass ClassClass.m -lobjc
ClassClass.m:1:2: warning: #import is obsolete, use an #ifndef wrapper in the header file
[s-okita@stoc s-okita]$ ./ClassClass
PolyTest
PolyTest2
オーバーライド(Overide)
ポリモーフィズムを実現するための機能です。子供のクラスで同じシグネチャのメソッドを作成するとその実体に対するメソッドを呼び出します。
[s-okita@stoc objc]$ cat override_test.m
#import <stdio.h>
#import <objc/Object.h>
/* 本来はヘッダファイルに記述する */
@interface Pearent : Object
- (void) message;
@end
@interface Child : Pearent
/* オーバーライド */
- (void) message;
@end
@implementation Pearent
- (void) message
{
printf("persion instance\n");
}
@end
@implementation Child
- (void) message
{
printf("child instance\n");
}
@end
void call(id opaque) {
[ opaque message ];
}
int main(int argc, char *argv[]) {
id test = NULL;
test = [ Pearent alloc ];
call(test);
test = [ Child alloc ];
call(test);
return 0;
}
[s-okita@stoc objc]$ gcc -Wall -O2 -o override_test override_test.m -lobjc
override_test.m:1:2: warning: #import is obsolete, use an #ifndef wrapper in the header file
[s-okita@stoc objc]$ ./override_test
persion instance
child instance
オーバーロード(Oveload)
メソッド名が同じでもシグネチャが異なれば、コンパイル時にプログラムが判断してそのメソッドを呼び出します。C++/Javaのようにメソッド名だけではオーバーロードが実現できません。以下のサンプルのようにラベルが必要になります。
[s-okita@stoc objc]$ cat overload_test.m
#import <stdio.h>
#import <objc/Object.h>
@interface MathClass : Object
- (int) add : (int ) a I : (int ) b;
- (double) add : (double) a D : (double) b;
@end
@implementation MathClass
- (int) add : (int ) a I : (int ) b
{
return a + b;
}
- (double) add : (double) a D : (double) b
{
return a + b;
}
@end
int main(int argc, char *argv[]) {
id obj = [ MathClass alloc ];
printf("0\n", [ obj add : 1 I: 1 ]);
printf("0.000000\n", [ obj add : 1.0 D: 1.0]);
return 0;
}
[s-okita@stoc objc]$ gcc -Wall -O2 -o overload_test overload_test.m -lobjc
overload_test.m:1:2: warning: #import is obsolete, use an #ifndef wrapper in the header file
[s-okita@stoc objc]$ ./overload_test
2
2.000000
インタフェース
オブジェクト指向において、契約を実現させる機能の1つです。オブジェクトには状態と動作を持たせますが、動作(メソッド)をもっていることを保証するために利用したりします。Objective-Cは、JavaでInterfaceと呼ばれるものをプロトコル(@protocol)として実現しています。 言語に依存せず「この言語で、契約を実現させる機能は何か?」という意識をもつと他の言語でも理解しやすくなると思います。
[s-okita@stoc objc]$ cat interface.m
#import <stdio.h>
#import <objc/Object.h>
@protocol HTTPProtocol
- (void) GET;
- (void) POST;
@end
/* RFC2518 */
@protocol WEBDAV <HTTPProtocol>
- (void) MKCOL;
@end
@interface MyWebClient : Object <WEBDAV>
@end
@implementation MyWebClient
- (void) GET
{
printf("GET method\n");
}
- (void) POST
{
printf("POST method\n");
}
- (void) MKCOL
{
printf("MKCOL method\n");
}
@end
int main(int argc, char *argv[]) {
MyWebClient *client = [ [ MyWebClient alloc] init ];
[ client GET ];
[ client POST ];
[ client MKCOL ];
[ client free];
return 0;
}
[s-okita@stoc objc]$ gcc -Wall -O2 -o interface interface.m -lobjc
interface.m:1:2: warning: #import is obsolete, use an #ifndef wrapper in the header file
[s-okita@stoc objc]$ ./interface
GET method
POST method
MKCOL method
セレクタ
Classクラスと同様にポリモーフィズムを実現させるための機能です。コンパイル時にメソッド名はコーディングして決まっているため、それを利用して実行時にメソッドを決定する機能です。
[s-okita@stoc s-okita]$ cat Selector.m
#import <stdio.h>
#import <objc/Object.h>
@interface Pearent : Object
- (void) message;
@end
@interface Child : Pearent
- (void) message; /* override */
@end
@interface Child2 : Pearent
- (void) message; /* override */
@end
@implementation Pearent
- (void) message
{
printf("Pearent\n");
}
@end
@implementation Child
- (void) message
{
printf("Child\n");
}
@end
@implementation Child2
- (void) message
{
printf("Child2\n");
}
@end
int main(int argc, char *argv[])
{
/* メソッドの内部表現を保持する。ポインタみたいなイメージ */
SEL abstructMessage = @selector( message );
[ [ Child alloc ] perform:abstructMessage ];
[ [ Child2 alloc ] perform:abstructMessage ];
return 0;
}
[s-okita@stoc s-okita]$ gcc -Wall -O2 -o Selector Selector.m -lobjc
Selector.m:1:2: warning: #import is obsolete, use an #ifndef wrapper in the header file
[s-okita@stoc s-okita]$ ./Selector
Child
Child2
カテゴリ
継承以外にも既存のソースコードに手を入れることなく拡張できる機能があります。それがカテゴリです。
[s-okita@localhost objc]$ cat category_test.h category_test.m
#import <objc/Object.h>
@interface TestClass : Object
-(void)message;
@end
@interface TestClass (Hoge)
-(void)messageB;
@end
#import "category_test.h"
#include <stdio.h>
@implementation TestClass
-(void)message
{
printf("hello\n");
}
@end
@implementation TestClass (Hoge)
- (void) messageB
{
printf("hello category\n");
}
@end
int main(int argc, char *argv[])
{
TestClass *ts = [ TestClass alloc ];
[ ts message ];
[ ts messageB ];
[ ts free ];
return 0;
}
[s-okita@localhost objc]$ gcc -Wall -O2 -o category_test category_test.m -lobjc
category_test.m:1:2: warning: #import is obsolete, use an #ifndef wrapper in the header file
[s-okita@localhost objc]$ ./category_test
hello
hello category
別ファイル(category_sub.m)に新しいメソッドを作成する。
[s-okita@localhost objc]$ cat category_sub.m
#import "category_test.h"
@interface TestClass (FUGA)
-(void) appendMessage;
@end
@implementation TestClass (FUGA)
-(void) appendMessage
{
printf("append\n");
}
@end
[s-okita@localhost objc]$ gcc -Wall -O2 -o category_test category_sub.m category_test.m -lobjc category_sub.m:1:2: warning: #import is obsolete, use an #ifndef wrapper in the header file category_test.m:1:2: warning: #import is obsolete, use an #ifndef wrapper in the header file
これを再度コンパイルするとリンケージされて既存のクラスに機能追加をすることができます。この例の場合TestClassクラスにappendMessageメソッドを追加しました。もしmain()関数などが動的にメソッドを判断している場合はこの追加機能は非常に効果があります。このような簡単なサンプルでは分かりませんがこの延長上にOCP(OpenClosedPrincipal)というオブジェクト指向の最終形態が存在します。
その他
デバック
gccでコンパイルしているためgdbでのデバックが可能です。gdbの使い方が分かればC言語と同様なデバックが可能です。ただ、Objective-Cの最大の特徴が非常に動的な言語であるため動的にコーディングすればするほど、解析が困難になる可能性があります。
最後に
今回、数日かけてObjective-C入門を記述してみましたが、Objective-Cの特徴の1つは、C言語を忘れずにオブジェクト指向技術を身に付けることが可能ということです。
プログラミングをするとC言語はOSやTCP/IPの実装など今日のソフトウェアの基幹を占めているため避けてはとおれません。C++は学習する際やオープンソースを解読する際にC言語の知識が必要となりますが、実際にはC言語を使わずにコーディングできます。またC++同様、C言語上位互換であるにも関わらず言語仕様が非常に小さいことが理解できました。
今日のJava言語は仕様変更と多くのオープンソースソフトウェアや利便性で主力言語となっています。しかし発展するためにライブラリと仕様拡張をしなければならないというデメリットも背負わなければならない状態になってきました。C言語、Smalltalk、Objective-Cは「ソフトウェアに制御を持たせるのではなく、技術者に制御を持たせる」という原始的思想があるため膨大な仕様拡張はされてきませんでした。
Objective-C,C言語,C++,Javaを例にとると、それぞれの言語拡張がどのようにされているかなどを再認識できました。
また新たに「ソフトウェア開発効率を求めるがゆえに簡単に実装できるライブラリや仕様拡張をおこなうと、言語の寿命が短くなるのではないか?」という問いをこの言語から投げかけられました。
少し「言語は方言である」という問いの解答に近づいた気がします。
2004-11-06 15:05
参考資料
Objective-C Beginner's Guide(英語)
OBJECT-ORIENTED PROGRAMMING AND THE OBJECTIVE-C LANGUAGE(英語)
