最近のトラックバック

2021年7月
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
無料ブログはココログ

« iPhoneと単体テスト環境構築メモ | トップページ | Objective-Cの配列 »

2008.08.06

Objective-Cのここが嫌い

 iPhoneOSというプラットフォームとObjective-Cという言語にも徐々に慣れてきた。
 しかし、まだiPhone関係は具体的なビジネスの話にはなってない(それはデモができるくらいになってから営業活動を開始する予定)ので、毎日こればっかやるわけにはいかない。地道に金を稼ぐ仕事も大事で手は抜けないからね。
 面白さだけで判断すればiPhoneだけやってたいなあ。来週妻の実家へ行く(お盆なので)のだけど、当然Mac持参で開発続行です。

 さて、今日はObjective-Cのイヤな点を書いてみる。僕はC++でプログラミングの基礎を学び、その子孫(Java/C#)の言語で多くの仕事をしてきたので、C++ファミリーの常識と異なるところで非常に違和感を覚える。異教徒の国にやってきたわけだからな...

●「ぬるぽ」がない
 やはり最大の衝撃はここ。null参照のオブジェクトに対してメソッドを呼んだ場合、C++ではクラッシュ、Java/C#では例外が飛ぶ。が、Objective-Cでは単にその呼び出しが無視されるだけである。なので、非nullを想定してるところでnullが入っていた場合、実行がかなり進んでから異常に気づくことになるので、デバッグ効率が悪い。
 これは積極的にassertを入れるしかないのかなあ。これはメリットがよくわからない仕様だ。

●引数の型のみが異なるセレクタ
 セレクタについて不満な点。引数の型のみが異なるセレクタが異なるクラスに定義されていると、全く関係のないクラスであっても、idに対しての呼び出し時にコンパイラが警告を出す。出るのは警告だけだし動作は期待どおりになるんだけど、やはり気持ちが悪い。

 このようなことは実際にはすごく簡単に起きる。
 機能上関係のない2つのクラスA,Bがあって、それぞれインスタンスを一意に識別するキーとしてAはint、Bは文字列を使うとする。で、

Aでの宣言:
-(id) initWithKey:(int)key;
Bでの宣言:
-(id) initWithKey:(NSString*)key;

 というようなメソッドを書いた時点でもうこの制約にひっかかる。これはキツい。
 型まで一致してれば問題はないのだけど、さすがに全部の引数をidにするわけにもいかんしな。回避するには initWithIntKey みたいに型名を意識したセレクタ名にするしか思いつかない。id型に対しての呼び出しのときだけだからいいんじゃないの、と思う人もいるかもしれないが、[A alloc]とした時点で返るのはidなのでコンストラクタ系はほぼ全部対象になる。
 なにしろ、iPhoneOSのフレームワーク内を含め、全クラスの全セレクタに対して重複不可なので、うっかり重複することは非常によくありそうだ。


●配列の使い勝手の悪さ
 これも僕は相当にブチ切れている(不便さに怒ってマウスを机に叩きつけたことが3回はある)のだけど、長くなるのでまた今度。


 しかし救世主もいる。

 id型とセレクタを駆使すればほとんどスクリプト言語に変貌するし、Cと同様の#defineマクロもあるし、カテゴリを使えば既存のクラスの拡張もできるので、これらをうまく使えばJava/C#では不可能なくらいのアクロバティックなコーディングができる。やりすぎれば可読性は最悪になるけど、武器としては強力だ。さらに、iPhoneOSでもできるのかまでは調べてないけれど、MacOSでなら動的にクラスやメソッドを生成できるのでメタプログラミングもOKだ。
 こういうのを駆使して不便に思ったところを快適にするために足回りのコードを整備するのは、将来の開発時間を大幅に節約できるのでおいしい投資だし、どれだけ不便なところに気づくことができるかが腕の見せ所とも言える。

 それにしてもObjective-Cというのは、ほとんどアセンブラのマクロにすぎないプレーンなC言語と、バリバリの高級オブジェクト指向言語であるSmalltalkが強引に合体して奇妙な同居をしている。親和性はゼロ。まさに地獄からやってきた言語だぜ。

 あと、コア部分のヘッダファイルに

* Copyright 1988-1996, NeXT Software, Inc.

 などと書いてあるのを見ると感慨深いね。

« iPhoneと単体テスト環境構築メモ | トップページ | Objective-Cの配列 »

コメント

ちょっと面白かったんでツッコミ。

nilが無効化する作法はSmalltalkから来てるんですが、それは
aObj = [[[Hoge alloc] init] autorelease];
というお作法通りのコードが示すように、何らかのオブジェクトに入れ子のメッセージを送って次々に変形するパターンを多用するからです。入れ子で書きたいようなコードは基本的にその全体で機能しないと意味がないため、「無駄な中間監査は挟まない」というのがObjCの設計思想ということになります。その分元締めはしっかりする必要がありますが、慣れてくると(ObjC的には)この方が便利な仕様なのが見えてきますね。

> nilが無効化する作法はSmalltalkから来てる

「作法」が意味するところが不明ですが、すくなくともデフォでは Smalltalk の nil はちゃんと例外を挙げますので、これは ObjC 独自のダメ仕様です。何か別のものと勘違いしておられるのではないでしょうか。

if (anObj = [[[Hoge alloc] init] autorelease]) {
 // 正常処理
} else {
// alloc 失敗処理
}

とか書けたほうが綺麗という作法だったような?
例外処理とかはとても不得手な言語だったよ。

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: Objective-Cのここが嫌い:

« iPhoneと単体テスト環境構築メモ | トップページ | Objective-Cの配列 »