網羅的に様々な分野に触れていて良い本だと思ったんだがな..... 読んでみるとかなり酷かったので紹介します。
iPhoneアプリケーションプログラミング 技術評論社 ¥ 3,360 |
もうタイピングしてるだけでウンザリするわけだが、 どの程度酷いか理解してもらうために少し引用してみる。
「まず、この@propertyによる宣言は必須となりますが、インスタンス 変数を{aka '定義'}}するかしないか、メソッドを自分で書くのかどうか、 @synthesizeを書くのかどうかという点については、 状況によって変わります。 」
しかし どのような状況で変わるのかまったく説明がない。 あるとすれば以下の項目だろうか。
「プロパティageについてまず見てみましょう。オプションが何もないので ゲッタやセッタは指定されておらず、読み書き可能で、代入時はそのまま 代入されます。この場合、@synthesizeディレクティブを実装部記述 することで、同名のインスタンス変数ageに対しての代入や参照を行う ゲッタやセッタを背後で自動的に作り上げてプロパティとして機能する ようにします。 つまり、@synthesizeは文字通りメソッドを合成するということで実装部に記述します。整数データの場合は、単なる代入で多くの場合は問題ないでしょう。 」
いやいや、それまっったく説明になってないでしょう。「状況によって変わります=単なる代入で多くの場合は問題ないでしょう」。なに言ってるのかわかってますか?
次はもっとひどい。
「サンプルプログラムではnonatomicが付けられたプロパティがよく 見られます。これを書かないようにする必要があるのは複数のスレッド から書き込みが行われるようなプロパティです。書き込みが同時に発生 しないような場合は nonatomicと書いておく方が 良いでしょう。 」
この「新居雅行」という筆者にとって、どうもプログラミング言語というものが 「ああ、星が綺麗だな」とか「溶岩が吹き出ている」といった 現象として見えている ようだ。でもApple][やVIC-1001の頃から30年くらいコンピュータを学んできた程度の青二才に 言わせてもらえれば、
仕様とは、Aという入力があれば必ず(バグを除き)f(A)という出力が 得られるもの。言い換えれば 思想 とも言うべきものだ。 ま、単なる素人には、状況や場面に応じて「ああ、書式が違うんだな」という 把握の仕方はありかもしれんけどさ、 そうなってしまう理由 、つまり必然があるのが プログラミング言語なんですよ。それを伝えるのが プロ の物書きとしての 義務なんじゃないの?
全体的に「あれもあります〜」「これもあります〜」「こういう可能性があります〜」と いう文体から、 実は全く内部構造を理解しないで本を書いている というのが伺えるけどね。
「続いて、familyNameとgivenNameの場合を見てみます。ageと違って retainという記述があります。このretainについては次の節で説明 しますが、こちらは基本型ではなく、オブジェクトへの参照がプロパティ です。オブジェクトを引数に取るメソッドについては、 原則 としてこの ように代入時の動作を既定するオプションとしてretainを宣言するか、 あるいはcopyによってオブジェクトそのもののコピーを記録することを 行います。単なる参照の代入では、オブジェクトの開放との兼ね合いに 問題が出る 可能性があるので、 」
真面目な話、 この人の文章を初心者が読んだら混乱するだけ だぞ。 そういう意味ではAmazonの書評は全く正しいな。これは確かに初心者向けじゃない (むろん玄人向けでもないが)。 プロパティにしても、これは他言語からの概念で、オブジェクト指向含めて周辺的な知識を 網羅的に持っている人間には何が言いたいかわかるだろうけど、そんな人は読む必要もないだろ。
ちなみに手元のLinux gccには@propertyが無かったし(え?)言語仕様も知らないで(え?) propertyの説明を書いてみる。当然間違ってるだろう(笑)。
ここまでが導入。
以上がプロパティの仕様。
結局のところ「ただ単に文字列を内部でコピーして保持するセッタ」を「Cでオブジェクト指向っぽっく書く」と、以下のようなコードになるだろう。これを@property(copy)と@synthesizeで終わらせてしまえるのだから、メンバ変数が多くなればなるほどObjective-Cが有利なのは疑いない。 エラー処理がほとんどないのと、スレッドセーフの手段がグローバルロックなのは手抜きである。申し訳ない。
static CRITICAL_SECTION lock_; void setFamilyName(id obj, char *newname) { int len; char *tmp; if (obj == NULL || newname == NULL) return; ENTER_CRITICAL_SECTION(lock_); len = strlen(newname); tmp = (char *)malloc(len + 1); if (tmp == NULL) { LEAVE_CRITICAL_SECTION(lock_); return; } strcpy(tmp, newname); if (obj->name != NULL) { free(obj->name); } obj->name = tmp; LEAVE_CRITICAL_SECTION(lock_); return; }
まあ正確性に関してはマジ墓穴というか
という感じで赤面状態なわけだが、久々に高い本で腹が立ったので書いてみた。