昨日投稿を読んで、私は例外の起源についてあまり知らないことに気付きました。OOP関連の概念のみですか?私はそう思う傾向がありますが、やはりデータベースの例外があります。
goto
。特に、スローは、ブロック構造のネストに基づいてコンテキストによって決定されます。そのため、例外は、単一の出口原則がガイドラインではなく絶対的なものである、やや緩やかな構造化プログラミングにも依存しています。
昨日投稿を読んで、私は例外の起源についてあまり知らないことに気付きました。OOP関連の概念のみですか?私はそう思う傾向がありますが、やはりデータベースの例外があります。
goto
。特に、スローは、ブロック構造のネストに基づいてコンテキストによって決定されます。そのため、例外は、単一の出口原則がガイドラインではなく絶対的なものである、やや緩やかな構造化プログラミングにも依存しています。
回答:
例外はOOPの概念ではありません。
しかし、1つの小さな点でも、完全に無関係ではありません。
他の答えが示したように、例外の概念は、いくつかの非OOP言語でそれを作りました。その概念の何もOOPから何かを必要としません。
しかし、OOP を真剣に扱うOOP言語のすべてではないにしても、例外を必要とするのは、エラー処理の他のメソッドが特定の1点で失敗するためです:コンストラクター。
OOPのポイントの1つは、オブジェクトがその内部状態を完全に一貫してカプセル化および管理することです。これも手段は純粋なOOPにあなたが「アトミック」conistent状態で新しいオブジェクトを作成するという概念が必要であること-初期化する(必要な場合)のメモリ割り当てからすべてをに意味のある状態必要があります(メモリをゼロつまり、単純なは十分ではありません) 1つの式で行われます。したがって、コンストラクターが必要です。
Foo myFoo = Foo("foo", "bar", 42);
しかし、これは、コンストラクターが何らかのエラーのために失敗する可能性があることを意味します。エラー情報を例外なくコンストラクターから伝達する方法は?
戻り値?一部の言語でnew
はnull
意味のある情報のみを返すことはできても、返すことができないため、失敗します。他の言語(C ++など)ではmyFoo
ポインターではありません。確認できませんでしたnull
。またmyFoo
、エラーについて尋ねることはできません。エラーは初期化されていないため、OOP思考では「存在しません」。
グローバルエラーフラグ?状態をカプセル化してからグローバル変数をカプセル化することについてはどうですか?hに移動... ;-)
混合物?決して良くない。
?
したがって、例外はOOPよりも基本的な概念ですが、OOPは自然な方法で例外に基づいています。
OOP関連のみですか?
いいえ。例外とOOPは無関係です。
例外処理は、エラーを処理するメカニズムです。例外は、実行の現在の状態を事前定義された場所に保存し、実行を例外ハンドラーと呼ばれる特定のサブルーチンに切り替えることで処理されます。
C(実際にはOOP言語ではなく、何らかの方法でCの例外をエミュレート可能)とC ++(OOP、例外をサポート)を比較すると、Cの標準委員会がCに例外処理を追加することを妨げるものは何もありませんが、CはOOP言語にはなりません。
ON ERROR GOTO xxxx
try catch
。
例外は、簡単に言えば、注意を必要とする例外的な状況であり、多くの場合、プログラムの実行フローの変更です。その定義により、例外と例外処理はオブジェクト指向に限定されず、単純なプログラムエラーは例外の一形態と見なすことができます。
通常、オブジェクト指向言語にはネイティブ例外クラスがあり、コンテキストによっては、「例外」という言葉が実際には一般的な概念ではなくネイティブクラスを指す場合があります。オブジェクト指向の例外処理は、ほとんどのオブジェクト指向と同様に構文糖衣であり、決定的に非オブジェクト指向の言語で簡単にエミュレートできます。Cプログラミングwikibookの Cの例を次に示します。
#include <stdio.h>
#include <setjmp.h>
jmp_buf test1;
void tryjump()
{
longjmp(test1, 3);
}
int main (void)
{
if (setjmp(test1)==0) {
printf ("setjmp() returned 0.");
tryjump();
} else {
printf ("setjmp returned from a longjmp function call.");
}
}
答えは簡単です。
例外を伴う非OO言語の良い例はADAです。
ここですでにいくつかの非常に良い答えがあります。例外がある非OOPプログラミング言語の他の例:
Oracle PL / SQL
古典的なVisual Basic(V6以前では、「On Error Goto」は例外処理の形式です)
(要点:両方の言語でいくつかのOO要素を見つけましたが、例外処理メカニズムはそれらを使用していません。概念はこれらの言語にOO要素が追加される数年前に導入されたためだと思います)。
例外の背後にある基本的な考え方は、プログラマが「通常の」実行パスをより簡単にたどることができるように、プログラムフローをクリーンアップすることです。Cでファイルを開くという単純なケースを考えてみましょう。ファイルを開こうとした直後、プログラマーはfopen()呼び出しからの応答を調べ、呼び出しが成功したかどうかを判断する必要があります。呼び出しが成功しなかった場合、プログラマーは適切に応答する必要があります。「通常の」実行パスの次の呼び出し、おそらくfread()またはfwrite()の呼び出しは、エラーまたは障害状態が処理された後に表示されます。次の画面に表示される場合があります。
例外を提供する言語では、同等のfopen()呼び出しの直後にfread()またはfwrite()を実行できます。「通常の」実行パスの「次のステップ」を隠しているエラー処理はありません。プログラマは、1つの画面で通常のパスをより多く見ることができるため、実行をより簡単に追跡できます。エラー処理はプログラムの別の部分に移動します。
例外自体はOOPの概念ではありませんが、OOPの概念を使用して実装されることが多く、それらにより便利で強力になります。たとえば、例外は継承階層で定義できます。ファイルを開いたり読み書きしたりする概念的な例を使用すると、これらの呼び出しはそれぞれ、FileClosedException、DeviceFullException、NoSuchFileException、InsufficientFilePermissionsExceptionなどのさまざまな例外を生成する可能性があります。 GenericExceptionを継承します。
プログラマーが概念をテストするために迅速で汚れた実装を行っている場合、例外処理をほとんど無視して、GenericExceptionの単一のハンドラーを実装するだけです。そのハンドラーは、GenericExceptionと、GenericExceptionから継承するすべての例外を処理します。ファイル関連の例外を同じ方法で処理したい場合は、FileExceptionのハンドラーを作成できます。FileExceptionsおよびFileExceptionを継承するすべての例外に対して呼び出されます。さまざまなエラー条件に対して異なる応答をするプログラムを作成する場合、特定の例外ごとに特定のハンドラーを作成できます。
他の人は、言語の例で「いいえ」と正しく答えています。OOPを一切使用せずに言語に例外を追加する方法の例を追加することで拡張できると考えました。
このようなアカデミアに適した言語であるOZのDSKL(宣言型シーケンシャルカーネル言語)の場合にこれを行います。DSKL(またはDKL)は、ここ(ランダム検索結果)のステートメントと値の部分にあります。正確な定義は重要ではありませんが、これは修正可能な変数を持たない非常に単純な言語であり(変数は宣言され、後でバインドされます)、OOPは組み込まれていません。
OOPは、このカーネル言語に言語の抽象化として追加することさえできません。カーネル言語(NewName)に一意の名前を追加し、ローカルスコープを使用することで、カプセル化を実現できます。または、カーネル言語(NewCell)に可変状態を追加し、ローカルスコープを使用して、適切なOOPとカプセル化を実現できます。ただし、指定されたカーネル言語だけでは実現できません。
その後、カーネル言語に例外を追加すると、OOPがサポートされていない言語になりますが、例外が発生します。方法を示しましょう:
スタックとストレージを備えた抽象マシンを定義することで、言語の各ステートメントの実行内容(ステートメントのセマンティクス)を定義できます。たとえばskip
、スタック内では何もしない、A = 3
スタック内ではAを(/ with)3にバインドする必要があります。
まず、例外を定義する方法の構文を追加します。これを行うに<statement>
は、DKLに別の2つの句を追加します。
<statement> ::== ... (old stuff)
| try <statement> catch <id> then <statement> end
| raise <id> end
既知のtry / catchと、例外を発生/スローする方法を次に示します。
抽象マシンでどのように動作するかによってセマンティクスを定義します。
試す
セマンティックステートメントは次のとおり(try <statement1> catch <id> then <statement2> end)
です。
(catch <id> then <statement2> end)
(<statement1>)
ステートメント1はスタックの一番上にあり、最初に実行されたことに注意してください。
上げる
セマンティックステートメントは次のとおり(raise <id> end)
です。
(catch <id> then <statement> end)
(<statement>)
the stack という形式で、キャッチを取得しました。Catch
通常の実行中にcatch-statementが表示される場合、これは、このレベルまで例外を発生させずに内部で実行されたものを意味します。したがってcatch
、スタックをポップして、何もしません。
QED、例外があり、OOPの可能性がない言語があります。
環境の部分を抽象マシンから削除して、よりシンプルにしました。