ハローブレーブニューワールド

科学者のためのCocoa(パート1):ハローブレーブニューワールド
英語チュートリアルの作成日:2006年10月17日
日本語版作成日:2010年一月2日
著者:Drew McCormack
英語のチュートリアル:MacResearch.org
翻訳:Ignacio Enriquez なちょ4D


Objective-Cに異議?


私は最近、MacResearchに入ったが、私はサイトとそのコンテンツにどのような貢献ができるか決めなければなりませんでした。この過去数年間で 定期的にCocoa開発のオンライン記事を書き、それら最終的にになりました。なので、Cocoaのことは論外ではありませんでした。しかしならが、私は研究者(理論化学)でもあり FortranとCのような恐竜で日々プログラミングしている。そして、科学プログラミングのいつくかの短いコースも書いたことがあります。 私がまだしていないことは、ScientistsのためにCocoaのコースを開発することです、そして、出来事の驚異の並置で、私は現在、まさしくそれをする立場にいます。

Cocoaを学ぶ多くの場所があります、(アップルのドキュメンテーションも)しかし科学者や科学者プログラミングを明確に対象とした素材はありません。私の経験では、科学者はあまりに多くの時間を浪費する余裕がないし、ちょっと昔の技術に深く取り入り込んで新しく紹介された概念を理解するのに困る人は少なくなく 科学者はCocoaの様な新しい技術を学ぶときに特別な扱いをする必要があります。結局
研究/科学はメインですから。

このチュートリアルのシリーズでは、Java、C#よりも むしろFortran、Cに慣れた人の好みに合う方法でアップルのフレームワークを紹介したいと思います。私は多くの科学的開発者にとって オブジェクト指向(OO)のような慣れない概念について話し、Fortranのような手続き型言語にすこし戻ります。なぜなら、言語の設計の動機を強調し そのメリットと潜在的デメリットをハイライトするためであります。 

もちろん、Objective-C言語はCocoaの一つの局面にすぎません。或るものが最も小さい方の局面を言いさえするでしょう。残りはフレームワーク自体であり、(あなたにあなたの友人を感動させるようにうわべだけのグラフィカルインタフェースを開発して、何らかの役に立つ研究をたぶん容易にさえさせます)。 それも始めるつもりですが、かなりの大多数のCocoa導入と異なって、私たちはコンピュータの科学者が最も付き合い易いところから出発するつもりです: コマンドラインで。 その後、私たちは、グラフィカルなプログラムを開発するためにアップルのIntegrated Development Environment(IDE)、Xcode、に移るつもりです。

私が提示する例は必ず簡単になるでしょうが、隣人の子供さんの興味が引かれるかもしれないものよりむしろ科学者に最も関心があるアプリケーションのタイプを狙うつもりです。 道に沿った話題は以下を含みます。構文解析/データのインポート。 テーブルとプロートによるデータの提示。ビジュアリセーション。そして、グラフィカルインタフェースで既存のレガシのあるツールを包装すること。

私は、かなり短くチュートリアルを保つことを望んでいます。私たちのだれにも多くの時間がなくて、あなたは一つの長い怪物より多くの簡潔なチュートリアルを読みこなすことができそうですね。私がどのくらいの時間を開けてもよいかによって、チュートリアルは2−3週に1回現れるでしょ。 (あなたが気付かなかったかもしれないが、MacResearchはボランティアに基づいて走ります。)


Objective-Cって醜いですか? 私は反対します!


今日、醜いアヒルの子にあなたを紹介することによって、始めたいと思います: Objective-C。 確かに非常に醜いかもしれませんね。Cベースのプログラミング言語であるC++、Javaのように幾つかの採用されたコンベンションに従っていないからです。Objective-C言語は実に美しい(swan)白鳥であることを保証したいと思います。数週間後Objective-Cと遊んだあとに、結局あなたは同意するようになると確信している。皆そうなります。

実際にObjective-CはC言語のスーパーセットであり、オブジェクト指向言語スモールトーク フランケンシュタインハーフです。メアリー・シェリーの怪物のように、構文は初めに、少し恐ろしい場合がありますが、2、3日後に、あなたは、他の言語がなぜObjective-Cのようにしないかと思うでしょう。 もっとも、これに関して話すより見せます。以下、私たちの最初のObjective-Cプログラムであります:


#import <Foundation/Foundation.h>

// -----------------------
// スタンダードインプットで入力する
// スペースで区切った数字の列の総和を計算するプログラム
// -----------------------
int main(int argc, char *argv[])
{
int retCode = 0;
NSAutoreleasePool *pool = [NSAutoreleasePool new];

// ファイルハンドルの取得
NSFileHandle *fileHandle = [NSFileHandle fileHandleWithStandardInput];
NSData *inputData = [fileHandle readDataToEndOfFile];
NSString *inputString =
[[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding];

// ストリングをスペークで区切って、数字に変換
NSArray *tokens = [inputString componentsSeparatedByString:@" "];
double sum = 0.0;
unsigned int i;
for ( i = 0; i < [tokens count]; ++i ) {
sum += [[tokens objectAtIndex:i] doubleValue];
}
// 出力
NSLog(@"数字の総和は %g.", sum);
// 開放
[inputString release];
[pool release];
return retCode;
}


Xcodeの複雑さを避け、Objective-Cに特に魔法であるものがないことを見せるためにターミナルでCGGコンパイラでコンパイルします。私たちの目的はObjective-Cの途方に暮れないことです。 Capische?(カピーシュ?)


もし既にインストールしていなければXcode開発環境を整える必要があります。CGGコンパイラは中に含まれます。デベロッパーツールインストーラはMac OS Xインストールディスクにあります。それかアップルのデベロッパーサイトからダウンロードすることができます。(警告:ダウンロードのファイルのサイズが1GB以上)

デベロッパーツールのインストールが済んだら好みのテキストエディターで上記のコードをAdder.mファイルに書きます。次にターミナルに行き、次のコマンドでコンパイルします。


gcc -ObjC -o adder Adder.m -framework Foundation

今度./adderで実行します。スペースで区切ったいくつかの10進数を入力します。そしてCtrl+Dでスタンダード入力のパイプを終了します。
数字の総和が出てくる筈です。以下はセッションの例です。


./adder
1.24 2.35 245.1
2009-12-31 16:35:41.788 adder[1985:903] 数字の総和は 248.69.



Objective-Cコードのコンパイル


コンパイルコマンドで始まって、ただ今起こったことを調べましょう。通常Cocoaで開発するとき Xcodeは全部やってくれるからあんなコマンドを打つ必要がないが、Objective-CのプログラムをコンパイルすることはC言語のプログラムと同様であることを示したかっただけです。-ObjCというフラグを入れ、.cよりも.m拡張子を各ファイルに追加し そしてFoundationフレームワークにリンクする必要があります。(以前Mac OS X用にコンパイルしていなければ -frameworkリンクオプションと親しみではないが、ライブラリオプション-lと同じだがフレームワーク用ですね)

FoundationフレームワークはCocoaの一部である。上記のプログラムでは#importプロセッサ指示を利用してインポートされている。(#importはObjective-C言語のCの標準指示の拡張の一つである)FoundationフレームワークはAdder.mで使用しているクラスを提供してくれます。例えばNSString、NSData。(なぜNS?と聞いているならばNSの接頭語が名前の競合を防ぐためにCocoaで全体的に用いられている。そしてNSはMac OS Xの先祖であるNeXTStepの略である)


クラスとオブジェクトの導入


クラスは、Cの構造体structs、またはFortran90のユーザ定義された型と同様ですが、より強力です。 私たちは、クラスの詳細な議論を後にしますが、取りあえず知るべきなのは 各クラスがタイプを表現します。そしてクラスは変数の形でデータを含むことができます。メソッドも含むこともできます。メソッドはCとFortranの関数と手続きと同じようなものですが、違いはメソッドは特定なクラスに属するのです。

CとFortran 90では特定のタイプのの変数を定義できます。例えばCのプログラムは以下のようなコードがありえます。


struct Cow {
float weight;
};
struct Cow c;

それをFortran 90で以下のようです

type Cow
real :: weight
end type
type (Cow) :: c

両方はインスタンス化の例です。Cowタイプまたは型のcという名前を持った変数またはインスタンスを生成しています。

Objective-Cにおいてクラスで同じことができます。クラスのインスタンス化をするときインスタンスまたはオブジェクトを取得します。Adder.mでインスタンス化の例は:

NSAutoreleasePool *pool = [NSAutoreleasePool new];

現時点ではNSAutoreleasePoolクラスはなにをするか心配しないで オブジェクトの生成の工程に集中しましょう。この場合、変数はpoolと呼ばれます。(オブジェクト自体よりも 実はオブジェクトへのポインタであることに気付きましょう、Objective-Cでは常にこのようなやりかたをします。)NSAutoreleasePoolに属するnewメソッドによって poolにオブジェクトが割り当てられます。

再びオブジェクトのインスタンス化の詳細な議論を後にしますが、取りあえずクラスは特定なタイプの変数とメソッドを持っています。そして、クラスをインスタンス化するとオブジェクトを取得することができます。


メッセージとメソッドの導入


このチュートリアルを仕上げるために、メッセージングに焦点を合わせたいと思います。 上記のコードの行でメッセージングの例をちょうど見たところです。メッセージングとはオブジェクトかクラスにメッセージを送ることで、FortranかCの関数か手続きを呼ぶことと同様ですが、同等ではない。Objective-Cでメッセージを送る構文は大括弧を使用します。例えばAdder.mでは:

NSArray *tokens = [inputString componentsSeparatedByString:@" "];

このメッセージの名前はcomponentsSeparatedByString:であり、オブジェクトinputStringに送られます。(名前はコロンを含むことに注意、これをまもなく議論をします。)@" "はObjective-Cのストリングの意味をします。特にこの場合は空白文字の意味です。 このコードはメッセージcomponentsSeparatedByString:をinputStringに送り、空白文字のストリングを引数として渡しています。
Fortran90では恐らくこの様になります:

character(len=100) :: tokens(10)
character(len=100) :: inputString
inputString = "Hello there"
tokens = ComponentsSeparatedByString(inputString, " ")

大括弧はある意味では、ものを逆順にする。例えば、Fortran 90の関数ではオブジェクトinputStringは第1引数として渡されています。Objective-Cでは関数(あるいはオブジェクト指向の用語を使ってメソッド)はinputStringに属するから 明示的に引数として渡す必要がありません。自動で渡されます。
引数2つ以上があると更に変になります。例えば次ぎのコードでは

NSString *inputString = [[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding];

まず、ここにはメソッドが2つあります。片方はもう一つのやつの中にネストされています。
一番目の方は簡単:alloc. 引数無し、従ってコロン無し。Objective-Cでは引数一つに対してコロン一つがあります。
二番目の方はより複雑です。メッセージがallocメソッドの結果に送られます。二番目のメッセージの名前はinitWithData:encoding:です。Objective-Cにおいてこのような名前はselectorといいます。メソッド名と同じようなものです。二つのコロンに対応する二つの引数があります:inputDataとNSUTF8StringEncodingです。

もっとも紛らわしいことは恐らく、メッソド名は各コロンあたり1つに分けられるということです。これをはっきりするために、Cの同類の関数にコールを見てみましょう。

NSString *inputString =
InitWithData_Encoding_( AllocString(), inputData, NSUTF8StringEncoding );

Cの関数にコロンがあってはいけないため代わりにアンダーバーを使いました。多くの言語でもそうですがCでは関数名は連続しているがObjective-Cでは引数と混ぜていることに注意してください。
これはObjective-Cを初めて勉強するときに多分一番分かりにくいことだと思います。殆どの人々にとって新しく慣れるまでは少し時間がかかるかもしれません。しかし、慣れることを確信している。(長くは掛からしません)
そして、一回慣れたらこの仕組みの利点が見えるようになります。それらを次に説明します。
最初、 実はメソッド名をセグメンテーションに分けることは任意であることを指摘するベキですね。Cの方法のようにメソッド名を使うことが出来ますので、以下のコードも書くことができました。

NSString *inputString =
[[NSString alloc] initWithData_encoding_:inputData :NSUTF8StringEncoding];

この方法では、Objective-Cにとって文法的に大丈夫、メソッド名を始めに全部つめました。大括弧とコロンの使用は別として、このコードはCに大変似ていますね。よってCのようなメソッド名は可能ですが、Objective-Cにとらわれないのです。そして、このメソッドは前挙げたメソッドと交換可能ではないと強調したいと思います。単に異なる命名方法が可能で、他言語と同様なものが使えることはポイントですね。

こういったセグメンテーションされた命名というObjective-Cのアプローチは実は他の言語よりflexibleであります。自分のメソッド名をセグメントに分けることで引数をより説明しやすくなります。コード自体がドキュメンテーションになるので、結果的に読みやすいコードになります。そして説明用の多くのコメント書く必要がなくなります。更に普段のように引数の調べをする必要がなくなります。
CやFortranでプログラミングするときよく関数の引数やその順序を調べますが、Objective-Cでは一般にそれは明白です:

[NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:error];

(英語の)文かのように読め 今度のチュートリアルで説明するようにXcodeのコード入力補助機能があるので、全ての文字を書く必要がありません。


終わりに


取りあえずここまでです。このチュートリアルの一つだけを身に付けたければ、Objective-Cのメッセージングの仕組みにしてくださいね。それについて次のチュートリアルまでじっくり考えてください。そして、そのアイディア・概念に慣れるようにしてください。
最初これは多くの人々がもっとも恐れるものですが、もっとも使われているアプローチではなく裏には原理があるからです。
一旦メッセージングの構文を身に付いたら残りは楽勝なはずです。

もしAdder.mにまだ沢山のことが分からないことに心配しているならば、心配しないでください。そのときになったらちゃっと取り組み積もりだからです。今日のレッソンではObjective-Cの見た目にあなたを慣れさせるように設計されただけです。それ以上ではないものです。
次回は言語をもう少し詳しく調べるつもりです、メッセージングはどのように働くかを取り組み、そしてクラスの書き方も習います。

コメント

このブログの人気の投稿

クラッシーココア

生きているものたち