TOP

Objective-C入門 Mac OSX編

目次へ戻る

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(英語)

WisdomSoft

Objective-C Tips in my site.(English)

目次へ戻る


イバラキングへのリンク Get Firefox Valid XHTML 1.1 Apple Darwinへのリンク