8

デスクトップ Mac OS X で使用するために、Java コードベースを Cocoa/Objective-C に移植する作業を行っています。Java コードには、次のようなチェック済みの例外を伴うメソッドがたくさんあります。

double asNumber() throws FooException {
    ...
}

これらを Objective-C で表現する最良の方法は何ですか? 例外またはエラー出力パラメータ?

- (CGFloat)asNumber { 
    ... // possibly [FooException raise:format:];
}

また

- (CGFloat)asNumberError:(NSError **)outError {
    ...
}

通常、Objective-C では out-errors の方が優れたソリューションであると私は感じていますが、ご覧のとおり、上記のような多くのメソッドはかなりぎこちなく見えます。繰り返しますが、これらはたくさんあります。

もちろん、これらはJava のチェック例外であるため、これらのメソッドが呼び出される場所 (多くの場所) に@tryブロックまたはチェックを追加する必要があることに注意してください。if (*outError) {...}

Objective-C ではブロックに入るのがかつて高価でしたが、64 ビットまたは SL またはその他の新しい環境では安価であると聞いたことを思い出し@tryます (正確には思い出せません)。下位互換性についてはまったく気にしていないので、最新のホットさだけを考えて設計したいと思っています

4

6 に答える 6

16

文字列から数値を解析するなどの例外は絶対に避けるべきです。Objective-C では、例外はプログラマーのエラーを表し、ユーザー入力エラーや使用できないファイルでさえありません。(理由の一部は、例外処理は常に「従来の」エラー処理よりもコストがかかり複雑であるためです。ブロックに入ること@tryは 64 ビットでは「コストがゼロ」であるという事実に関係なく、実際に例外が発生するたびに依然として低速です。 ) もちろん、好きなように例外を使用することは許されていますが、それは Cocoa の方法ではなく、他の Objective-C コードと対立していることに気付くでしょう。あなたのコードを使用する人は、エラーになるはずの場合に例外をスローすることに非常に腹を立てるでしょう。

Apple自身のドキュメントから:

「多くの環境では、例外の使用はかなり一般的です。たとえば、ファイルが見つからない場合やデータを正しく解析できなかった場合など、ルーチンが正常に実行できなかったことを通知するために例外をスローする場合があります。例外はリソースを大量に消費します。 Objective-C. 一般的なフロー制御に例外を使用したり、単にエラーを示すために例外を使用したりしないでください. 代わりに、メソッドまたは関数の戻り値を使用してエラーが発生したことを示し、問題に関する情報をエラーオブジェクト。」

組み込みの Cocoa クラスがこのようなエラーを処理する方法を見てください。たとえば、NSString-floatValueには、失敗した場合に 0 を返すようなメソッドがあります。特定の状況に対するより良い解決策は、NSScannerがどのようにそれを行うかです。たとえば-scanFloat:、結果が格納されるフィールドへのポインターを受け入れ、解析が成功したかどうかに基づいてYESorを返します。NO

Obejctive-C の規則とベスト プラクティスは別として、NSError は NSException よりもはるかに堅牢で柔軟であり、呼び出し元が必要に応じて問題を効果的に無視できるようにします。Cocoaのエラー処理プログラミング ガイドを読むことをお勧めします。注:パラメータを受け入れる場合は、クライアントがエラー情報を受け取りたくない場合NSError**に通過できるように設計することも強くお勧めします。NULL私が知っているすべての Cocoa クラスは、NSString を含むエラーに対してこれを行います。

移植されたコードは最終的に Java コードとはまったく異なるように見えるかもしれませんが、Java の同等のクライアントと同じクライアントではなく、Objective-C コードで使用されることを認識してください。間違いなく言語の慣用句に一致します。ポートは Java コードのミラー イメージではありませんが、結果として (Objective-C の場合) より正確になります。

于 2009-07-13T01:36:40.063 に答える
7

Cocoa では、例外は「プログラミング エラー」に対してのみ使用されることになっています。哲学は、アプリにそれらをキャッチさせ、ユーザーが行っていることを保存して終了するオプションをユーザーに与えることです。1 つには、すべてのフレームワークまたはコード パスが 100% 例外に対して安全であるとは限らないため、これが唯一の安全な方法である可能性があります。予測して回復できるエラーの場合は、通常は出力パラメーターを介して NSError を使用する必要があります。

于 2009-07-13T01:39:35.240 に答える
3

「通常、ObjC の場合は out エラーがより良い解決策です」というのは正しいです。Cocoa で例外をスローする API を見つけることはほとんどありません (API の前提条件を満たしていない場合を除きますが、その場合、動作はデフォルトで定義されていません)。

このコードがあなたを超えて存続し、他の Cocoa 開発者に採用されることを期待している場合は、out エラーを使用することをお勧めします。私は、Cocoa になじみのない人々が作成したコードに取り組んでおり、例外を惜しみなく使用しています。

于 2009-07-13T01:33:03.347 に答える
2

私はObjective-Cが使用するアウトエラーアプローチの大ファンです。例外を処理する必要がありますが、必要に応じてエラーを無視することもできます。それはすべて、「プログラマーは自分たちが何をしているのかを知っている」というObjective-Cの姿勢に適合しています。また、コードがtry-catchブロックで乱雑にならないため、Objective-Cは非常に見栄えの良い言語になります。

そうは言っても、検討する必要があるかもしれません。例外が無視されるシナリオはありますか?あなたが投げる例外は本当に重要ですか?変数をクリーンアップして続行する単純なcatchブロックを作成していることに気づきましたか?私は構文が好きで、Objective-Cは最も重大なエラーに対してのみ例外を予約しているので、エラーに傾倒します。

于 2009-07-13T01:42:45.720 に答える
2

これらのチェックされた例外は、エラーをより明確にマッピングしているように見えます。例外は引き続き使用できますが、例外的な状況のために予約する必要があります。

于 2009-07-13T01:51:23.057 に答える
-1

64 ビットの Obj-C ABI (ランタイム) はゼロ コストの例外を使用するため、例外はおそらく最良のアプローチであり、実際のコストなしでよりクリーンなコードを取得できます。もちろん、32 ビットでは古い setjmp/longjmp 例外がまだ使用されており、それらは C++ と対話しないため、それが目標である場合は問題があります。

于 2009-07-13T01:25:51.763 に答える