例外はOOPの概念ですか?


37

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


「Mr Goodenuf」(または同様の)が「気にせず、Goodenufだよ」と反応して例外を発明したことを一度読んだことがあります。スタイルいじめ。私は今、参考文献を見つけることができないようです-おそらく他の誰かが見つけることができます。どの言語が最初に追加されたかを知ることは興味深いでしょう。
Steve314

7
Haskellには例外があり、OOPではありません
ダニエル・グラッツァー

1
例外自体は厳密にオブジェクト指向ではありませんが、例外をオブジェクトとして定義し、これらのオブジェクトのインスタンスをスローおよびキャッチする一般的な慣行は明らかにOOPです。
-Dougvj

例外とGOTOの違いは興味深い質問です。
オースティンヘンリー

2
@Austin-例外は、「例外のスローは、構造化プログラミングの最も厳格な弟子の一部が絶対的であると主張する単一の出口点原則に違反しますが、そうする方法で制約のないスパゲッティ制御フローを許可しませんgoto。特に、スローは、ブロック構造のネストに基づいてコンテキストによって決定されます。そのため、例外は、単一の出口原則がガイドラインではなく絶対的なものである、やや緩やかな構造化プログラミングにも依存しています。
Steve314

回答:


5

例外はOOPの概念ではありません。

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

他の答えが示したように、例外の概念は、いくつかの非OOP言語でそれを作りました。その概念の何もOOPから何かを必要としません。

しかし、OOP を真剣に扱うOOP言語のすべてではないにしても、例外必要とするのは、エラー処理の他のメソッドが特定の1点で失敗するためです:コンストラクター。

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

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

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

  • 戻り値?一部の言語でnewnull意味のある情報のみを返すことはできても、返すことができないため、失敗します。他の言語(C ++など)ではmyFooポインターではありません。確認できませんでしたnull。またmyFoo、エラーについて尋ねることはできません。エラーは初期化されていないため、OOP思考では「存在しません」。

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

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

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


3
私の知る限り、この「回答」の中で実際に尋ねられた質問に対応する単語は「ない」だけです。残りはOOPの例外に関するようです-私に敬意を払って、これは漠然と関連するものまったく無関係なものの間のどこかを読みます-再び、質問の文脈で
-gnat

@gnat:TOはまた、例外の起源については知らないと言っています。したがって、OOの土地のどこに例外があるのか​​という少しの背景は、私にとっては問題ないように思えました。YMMV
AH

1
@AH最初の行は別として、私はgnatに同意しなければなりません、それは本当に質問に対処しません。gnatに対するあなたの応答は、「彼は例外の起源について知らない」というものでしたが、実際には例外の起源を与えず、オブジェクトのインスタンス化中に例外をランダムに使用しました。

みんな、真剣に?-1?他の答えのほとんどは、100%の点ではありません。補償するために私から+1。この答えは、壊れたクラスのデザインの世界で良い背景アドバイスを与えます。(修正:マルチステップコンストラクターの言及は避ける必要があります)
Jo So 14

44

OOP関連のみですか?

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

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

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


2
すでに通常のOSでサポートされているある種の例外があると主張することさえできます。プログラムをクラッシュさせ(キャッチされていない「例外」)、コアダンプとデバッガーを使用すると、スタックトレースも取得できます。
bhaak

12
80年代初期のMS BASICでも例外処理がありましたON ERROR GOTO xxxx
。– jwernerny

1
@bhaak彼はWindowsのメモリダンプについても話している可能性があります
-JohnL

11
@jwernernyエラー処理?はい。しかし、誰もその例外処理を呼び出さないでしょう。実際、(構造化された)例外処理とは通常対照的でした。
コンラッドルドルフ

1
@jwernerny、私が従うかどうかわからない。私が理解したように、例外処理はエラー処理を行う非常に具体的な方法です。例外を聞いたとき、私はいつも構造について考えますtry catch
アンディ

12

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

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

6
単なる構文糖ではありません。setjmpでは、フルスタックアンワインドおよび型ベースのキャッチハンドラを再作成するのは困難です。さらに、例外の特別なコンパイルは、setjmpでは真似できない利点をもたらします。
edA-qa mort-ora-y

3
説明の例外は例外的な状況だと嫌いです。エラーを正しく修正するための十分な情報が現在のコンテキストにないため、現在のコンテキストでエラー状況を解決できない場合、例外を生成(スロー)する必要があります。
マーティンヨーク


9

答えは簡単です。

例外を伴う非OO言語の良い例はADAです。


4
うーん、なぜADAはオブジェクト指向言語ではないのですか?確かに、ADA83にはポリモーフィズムはありませんでしたが、オブジェクトベースと見なすことができます。また、ADA95以降、言語は完全にオブジェクト指向です。
ヤンニス

私が知る限り、例外処理はADA83よりも古いため、ADA自体は例外処理を行う非OOです。
ウーヴェプロナス

2
@YannisRizos:Ada83にはパッケージと汎用パッケージがありますが、オブジェクトはありません。Ada95で導入されました。
ムーヴィシエル

2
@Yannis-多態性のないオブジェクトは、ネストされたブロックのない構造化プログラミングに似ています。多型は、OOPを定義する特徴の1つです。Ada95でさえ、実行時バインディングをサポートするタイプは、「クラス」ではなく「タグ付きタイプ」と呼ばれますが、もちろんそれは単なるスペルです。Ada 83にはバリアントレコードと他のさまざまなタイプがありましたが、OOPに固有の機能を提供するタイプはありません。Ada 83はモジュール式で構造化されていましたが、オブジェクト指向ではありませんでした。
Steve314

3
@Yannis-基本的に、Adaコミュニティの一部の人々(ほとんどの言語の支持者のように)は、機能は優れているが、お気に入りの言語には実装されていないことを受け入れることができず、そうでなければ信じるあらゆる種類の言い訳を作ります。しかし、優れた言語がすべての可能な優れた言語機能を必要とするというわけではありません(ただし、Adaデザイナーがそう考えたとは信じがたいです)。私は言語設計に対するミニマリストのアプローチを実際には信じていませんが、最大主義の言語も完璧ではありません。
Steve314

7

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

  • Oracle PL / SQL

  • 古典的なVisual Basic(V6以前では、「On Error Goto」は例外処理の形式です)

(要点:両方の言語でいくつかのOO要素を見つけましたが、例外処理メカニズムはそれらを使用していません。概念はこれらの言語にOO要素が追加される数年前に導入されたためだと思います)。


少なくともDOS上のQuickBASICバージョン(Visual Basicより前のバージョン; WikipediaによるとQB 4.5は1988、VB 1.0 1991)にはON ERROR GOTO構文を使用したエラー処理がありました。QuickBASICにもいくつかのオブジェクト指向の概念がありました(QB 4.5は何らかのクラスもサポートしていると思います)が、ほとんど伝統的なBASICを適切なオブジェクト指向言語と呼ぶのは難しいでしょう。[ウィキペディア ]
からCVn

5

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

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

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

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


3

他の人は、言語の例で「いいえ」と正しく答えています。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)
です。

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

ステートメント1はスタックの一番上にあり、最初に実行されたことに注意してください。

上げる
セマンティックステートメントは次のとおり(raise <id> end)
です。

  1. スタックにこれ以上ない場合は、停止して、キャッチされていない例外を報告します。
  2. そうでない場合は、スタックから最初のセマンティックステートメントをポップします。catchステートメントでない場合は、手順1に進みます。
  3. (catch <id> then <statement> end)
    Push on (<statement>)the stack という形式で、キャッチを取得しました。

Catch
通常の実行中にcatch-statementが表示される場合、これは、このレベルまで例外を発生させずに内部で実行されたものを意味します。したがってcatch、スタックをポップして、何もしません。

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

環境の部分を抽象マシンから削除して、よりシンプルにしました。


1

いや

IIRC、例外は最初のオブジェクト指向言語の前に現れました。知る限り、例外は初期のLISP実装によって最初にサポートされました。初期の構造化言語(ALGOLなど)および初期のOO言語(SIMULAなど)は例外をサポートしていませんでした。


もちろん、ALGON 68には例外(「イベント」)がありましたが、他にもすべてがありました。PL / Iにもそれらがあり(「ON条件」)、1969年からの使用を説明する文献があります。
ロスパターソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.