web-dev-qa-db-ja.com

例外はOOPコンセプトですか?

昨日の投稿を読んで、私は例外の起源についてあまり知らないことに気付きました。 OOP関連する概念のみですか?)私はそう思う傾向がありますが、やはりデータベースの例外があります。

37
John V

例外はOOPコンセプトではありません。

しかし、それらは1つの小さな点でも完全に無関係ではありません。

他の答えが示しているように:例外の概念はいくつかの非OOP言語でそれを作りました。その概念には何もない必須 OOPからの何か。

しかし、すべてではないにしても、すべてのOOP必要な言語OOP 真剣に他のエラー処理方法は特定の特定の場所で失敗するため、例外が必要ですポイント:コンストラクタ。

OOPのポイントの1つは、オブジェクトがその内部状態を完全かつ一貫してカプセル化および管理することです。これは、純粋にOOP 「アトミックに」一貫性のある状態で新しいオブジェクトを作成する-メモリ割り当て(必要な場合)から初期化意味のある状態(つまり、メモリの単純なゼロ化では不十分)まで、すべてを1つで行う必要があります。式です。したがって、コンストラクタが必要です。

Foo myFoo = Foo("foo", "bar", 42);

ただし、これはコンストラクターが何らかのエラーのために失敗する可能性があることを意味します。エラー情報を例外なくコンストラクターから伝搬する方法は?

  • 戻り値?一部の言語ではnewnullのみを返し、意味のある情報は返さなかったため、失敗しました。他の言語(C++など)では、myFooはポインターではありません。 nullに対してそれをチェックできませんでした。また、エラーについてmyFooに質問することはできません-これは初期化されていないため、OOPの考えでは「存在しません」。

  • グローバルエラーフラグ?状態をカプセル化してから、いくつかのグローバル変数についてはどうですか? hに行く... ;-)

  • 混合物?決して良くない。

したがって、例外はOOPよりも基本的な概念ですが、OOPは自然な方法でそれらに基づいています。

5
A.H.

OOP関連のみですか?

いいえ。例外とOOPは無関係です。

例外処理 は、エラーを処理するメカニズムです。例外は、現在の実行状態を事前定義された場所に保存し、実行を例外ハンドラーと呼ばれる特定のサブルーチンに切り替えることによって処理されます。

C( 実際にはOOP言語Cで例外をエミュレートする可能性がある )とC++(OOP、例外をサポート)を比較すると、何も妨げないCに例外処理を追加することからCの標準委員会は、CをOOP言語にすることはできません。

44
BЈовић

例外は、簡単に言うと、注意が必要な例外的な状況であり、多くの場合、プログラムの実行フローの変更です。その定義により、例外と例外処理はオブジェクト指向に限定されず、単純なプログラムエラーは例外の一種と見なすことができます。

通常、オブジェクト指向言語にはネイティブの例外クラスがあり、コンテキストによっては、Wordの「例外」が一般的な概念ではなく実際にそのネイティブクラスを参照する場合があります。オブジェクト指向の例外処理は、ほとんどのオブジェクト指向と同様に、構文上の砂糖であり、非オブジェクト指向言語で簡単にエミュレートできます。 Cプログラミングウィキブック の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.");
    }
}
12
yannis

答えは単純なNOです。

例外のある非OO言語の良い例はADAです。

9
Uwe Plonus

ここですでにいくつかの非常に良い答えがあります。例外がある非OOPプログラミング言語の他の例:

  • Oracle PL/SQL

  • クラシックVisual Basic(V6以前、「エラー時のGoto」は、例外処理のIMHOです)

(要注意:両方の言語でいくつかのOO要素を見つけますが、例外処理メカニズムはそれらを利用しません。この概念はOOよりも前に導入されたためと思います_要素がこれらの言語に追加されました)。

7
Doc Brown

例外の背後にある基本的な考え方は、プログラムフローをクリーンアップして、プログラマが「通常の」実行パスをより簡単にたどれるようにすることです。 Cでファイルを開く単純なケースを考えてみましょう。ファイルを開こうとした直後に、プログラマーはfopen()呼び出しからの応答を調べて、呼び出しが成功したかどうかを判断する必要があります。呼び出しが成功しなかった場合、プログラマーは適切に応答する必要があります。 「通常の」実行パスでの次の呼び出し、おそらくfread()またはfwrite()の呼び出しは、エラーまたはエラー条件が処理された後に表示されます。それは次の画面にあるかもしれません。

例外を提供する言語では、同等のfopen()呼び出しの直後にfread()またはfwrite()を続けることができます。 「通常の」実行パスの「次のステップ」を隠すエラー処理はありません。プログラマーは1つの画面でより多くの通常のパスを確認できるため、実行をより簡単に追跡できます。エラー処理はプログラムの別の部分に移動されます。

例外自体はOOPの概念ではありませんが、OOPの概念を使用して実装されることが多いため、例外がより便利で強力になります。たとえば、例外は継承階層。ファイルを開いたり読み書きしたりする概念的な例を使用すると、これらの各呼び出しは、FileClosedException、DeviceFullException、NoSuchFileException、InsufficientFilePermissionsExceptionなどのさまざまな例外を生成する可能性があります。 GenericExceptionから継承されるIOException。

プログラマーが概念をテストするために素早くダーティな実装を行っている場合、プログラマーはほとんど例外処理を無視し、GenericExceptionの単一のハンドラーを実装するだけかもしれません。そのハンドラーは、GenericExceptionおよびGenericExceptionから継承する例外を処理します。ファイル関連の例外を同様に処理したい場合は、FileExceptionのハンドラーを作成できます。これは、FileExceptionおよびFileExceptionから継承するすべての例外に対して呼び出されます。さまざまなエラー条件に対して異なる応答をするプログラムを作成したい場合は、特定の例外ごとに特定のハンドラーを作成できます。

5
MikeD

言語の例を挙げて「いいえ」と正しく答えた人もいます。 OOPを使用せずに、言語に例外を追加する方法の例を追加して拡張できると思いました。

DSKL(宣言的逐次カーネル言語) [〜#〜] oz [〜#〜] の場合にこれを行います。これは、このような学界に適した言語です。 DSKL(またはDKL)は、ステートメントと値の部分である here (ランダム検索結果)で確認できます。正確な定義は重要ではありませんが、これは変更可能な変数(宣言されて後でバインドされる)がなく、OOPが組み込まれていないため、非常に単純な言語です。

OOPを言語の抽象化としてこのカーネル言語に追加することもできません。一意の名前をカーネル言語(NewName)に追加し、ローカルスコープを使用することにより、カプセル化を実現できます。または、カーネル言語(NewCell)に可変状態を追加し、適切なローカルスコープを使用するOOPカプセル化を使用して実現できます。ただし、はできません指定されたカーネル言語のみで達成されます。

次に、カーネル言語に例外を追加すると、OOPサポートがない言語になりますが、例外があります。方法を説明しましょう:

スタックとストレージを備えた抽象マシンを定義することで、言語の各ステートメントが実行することを定義できます(ステートメントのセマンティクス)。たとえば、スタックのskipは何もしないでください。スタックのA = 3は、Aをbind(/ unify)する必要があります(/ with)3。

まず、例外の定義方法のsyntaxを追加します。これを行うには、DKLの<statement>に2つの句を追加します。

<statement>  ::== ... (old stuff)
                 | try <statement> catch <id> then <statement> end
                 | raise <id> end

既知のtry/catchと、例外を発生/スローする方法を次に示します。

これらのセマンティクスを、抽象マシンでどのように機能するかによって定義します。

試す
セマンティックステートメントは次のとおりです:(try <statement1> catch <id> then <statement2> end)
行う:

  1. セマンティックステートメント(catch <id> then <statement2> end)をスタックにプッシュします
  2. セマンティックステートメント(<statement1>)をスタックにプッシュします

ステートメント1はスタックの一番上にあり、最初に実行されます。

レイズ
セマンティックステートメントは次のとおりです:(raise <id> end)
行う:

  1. スタックに何もない場合は、停止して、キャッチされなかった例外を報告します。
  2. そうでなければ、スタックから最初のセマンティックステートメントをポップします。 catchステートメントでない場合は、ステップ1に進みます。
  3. (catch <id> then <statement> end)の形式で問題が発生しました
    (<statement>)をスタックにプッシュします。

キャッチ
通常の実行中にcatchステートメントが表示された場合、これは、例外がこのレベルまで発生せずに内部で実行されたものを意味します。したがって、スタックのcatchをポップするだけで、何もしません。

QED、例外があり、OOPの可能性がない言語があります。

抽象化マシンから環境の部分を削除して、単純化しました。

3
Matsemann

番号

IIRC、例外は最初のOO言語の前に表示されました。AFAIK、例外は、初期のLISP実装によって最初にサポートされました。初期の構造化言語(ALGOLなど)および初期のOO言語(SIMULAなど)は例外をサポートしていませんでした。

1
kevin cline