例外

無効な値や通信エラーなどの異常なイベントに Curl® 実行環境 (RTE) で遭遇することがあります。例外を使用して、このようなイベントに対応することができます。プログラムで例外を必ず使用する必要はありませんが、推奨されています。
この章では、Curl® 言語の例外について説明します。具体的には、以下のトピックについて説明します。

例外の概要

要約:
  • エラー処理には例外モデルを使用します。
  • 例外モデルは Java™ プログラミング言語や C++ の例外モデルと似ています。
  • 例外では、これをスローするコード ブロックの評価が終了され、プログラム自体の評価は終了されません。
  • エラーによりプログラムの実行が終了し、ディバガ へのアクセスを提供するエラー メッセージが表示されます。
Curl 言語では、異常なイベントの処理に例外モデルを使用します。例外モデルは、C++ や Java プログラミング言語の例外処理と似ています。例外モデルでは、例外オブジェクトを使用して異常なイベントに関する情報を格納します。Curl RTE が例外イベントを検出すると、例外をスローします。RTE は該当する例外オブジェクトを作成して、例外をキャッチするコードにプログラム制御を渡します。例外をキャッチしたコードは異常イベントを処理して、適切なエラー メッセージが表示できる場合はこれをユーザーに表示します。
予測可能な異常イベントを適切に処理するために、コードを書く際に Curl 言語の例外モデルを使用することを推奨します。たとえば、コードで特定範囲の値を前提条件とする場合、範囲外の値に対して例外を使用して、イベントを処理することができます。
大抵の場合は、例外をキャッチして処理するコードは例外をスローするメソッドの内部に入れます。ただし、例外をスローするメソッドの外側で例外をキャッチして処理する方が望ましい場合があります。この場合、メソッドの呼び出し側が任意に例外を処理することができます。
メソッドには、呼び出し側がキャッチを必要とする例外をスローするものがあります。このようなメソッドを呼び出す場合、例外をキャッチして処理するコードをインクルードする必要があります。メソッドがスローする例外のキャッチが必要かどうかを判別するには、『API リファレンス』でそのメソッドを参照してください。
例外がスローされると、RTE はコードの評価を停止し例外オブジェクトを作成します。例外オブジェクトには、例外発生時のプログラムの状態など、例外に関する情報が含まれます。次に、RTE は例外をキャッチするコードを検索して実行します。
RTE は、例外をキャッチするコードが見つかるまでスタックを逆方向に検索します。例外をキャッチするコードが見つからない場合、RTE (および結果的に現在のアプレット) はエラー状態で終了します。これは、スローした例外をキャッチしなければプログラムはエラー状態で終了することを意味します。

クラス階層

要約:
Exception はパブリッククラスで、RTE がスローまたはキャッチするさまざまなセキュリティ例外や、ユーザー コードがスローまたはキャッチするエラーおよび例外のすべてを含め、エラーおよび例外クラスはこのクラスを継承します。
IOException および DynamicLookupExceptionなど、特殊な目的を持つ例外クラスは Exception を継承します。さらに、このクラスを継承する新しいクラスも作成できます。ソース コード内の特定の操作のみでスローされる種類の例外を新たに作成する場合、およびソース コードの特定の位置でテストして処理する必要があるエラーの場合は、一般的に Exception またはこのクラスに組み込まれたサブクラスの 1 つをサブクラス化することをお勧めします。
RuntimeException は、さまざまな共通例外を含む Exception の重要なサブクラスです。この共通例外とは、多様なコードでスローされ、ソース コードで必ずしも予想され処理されていない例外のことです。組み込まれている RuntimeException サブクラスには、ArithmeticExceptionNullDereferenceException、および KeyNotFoundException があります。
Error はパブリック クラスであり、個々のエラークラスはこのクラスを継承します。通常、エラーは回復不可能な状況で使用されます。SyntaxErrorError を継承します。ランタイムでは、ソースコードの解析でこれらの例外を使用します。
ThrowableException と同意で、下位互換性を保つために保持されています。

例外クラスの作成

要約:
  • Exception を継承するクラスを作成します。
当然ながら、独自の例外クラスを作成してコード内で発生する問題を表示する必要が発生します。例外クラスを作成するには、Exception を継承するクラスを作成します。たとえば、次のコードでは MyException と呼ばれる例外クラスを作成しています。
{define-class public MyException {inherits Exception}

  {constructor public {default message:String}
    {construct-super message}
  }
}

例外の発生

要約:
  • throw 式を使用します。
例外をスローするには、throw 式を使います。throw 式の構文は次のとおりです。
{throw exception}
exception は例外オブジェクトです。exception のクラス タイプは、Exception のサブクラスである必要があります。たとえば、次のコードは MyException 例外オブジェクトをスローします。:
{throw {MyException "The value is zero!"}}
このコードでは、例外オブジェクトの message フィールドは文字列 "The value is zero!" に設定されています。message フィールドは String であり、テキストのメッセージを格納しています。

例外のキャッチ

要約:
  • try 式を catch 句および finally 句と使用します。
例外をキャッチするには、例外をスローするコードを try 式に含めます。次に、例外をキャッチする catch 句と、クリーンアップするオプションの finally 句を使用します。次の構文を使います。
構文:{try
    body
[catch-clauses]
[finally-clause] }
説明
bodyは、1 つ以上の Curl 言語の式 (例外をスローするコード) です。
catch-clausesは、0 以上のオプションの catch 句です。
finally-clauseは、オプションの finally 句です。
ランタイムでは、コードの実行が終了するか例外がスローされるまで body の式が評価されます。続いて catch-clauses を使用して例外をキャッチします。オプションの finally-clause 句がある場合、例外がスローされたかどうかにかかわらず、body の後でこれが評価されます。
catch-clauses の 1 つまたは finally-clause が例外をスローすると、現在の try 式が終了します。このような例外は外側の try 式でキャッチされます。

catch

catch 句の構文は次のとおりです。
catch e:exception-type do
    body
ここで、exception-type は例外クラスの名前、body は式です。たとえば、次のコードは flagfalse にして MyException タイプの例外を処理します。
catch e:MyException do
    set flag = false
try 式では、例外に対して最大 1 つの catch ボディが実行されます。catch 句は順番に調べられます。実行される catch 句は、スローされた例外のサブクラスである exception-type を持つ最初の catch 句です。
catch 句のボディでは、エラーを定義するかまたは明示的に例外をスローできます。このボディ内でスローされた例外から catch 句にアクセスすることはできません。したがって、新しい例外は外側の try 式でキャッチする必要があります。ただし、finally 句は catch ボディ内の新しい例外からアクセスできます。

finally

finally 句の構文は次のとおりです。
finally
    body
ここで、body は式です。たとえば、次のコードでは flagfalse の場合に resolve-exceptions と呼ばれるプロシージャを呼び出します。
finally
    {if flag == false then
        {resolve-exceptions}}

キャッチの使用例

次のコードでは、try 式を例示しています。コードは throw 式が含まれた my-proc というプロシージャを呼び出し、MyException タイプの例外をキャッチします。flagfalse に設定され例外が処理されます。次に、クリーン アップ タスクの一部として flagfalse の場合に resolve-exceptions と呼ばれるプロシージャを呼び出します。
{try
    {my-proc}
 catch e:MyException do
    set flag = false
 finally
    {if flag == false then
        {resolve-exceptions}
    }
}

エラーの通知

要約:
  • error 式を使用します。
エラーが通知されると、ランタイムはコードの評価を中止してエラー メッセージを表示します。Error タイプの例外をスローして、Curl コンソールおよびダイアログ ボックスにエラー メッセージを表示します。
エラーの通知には、次の構文の error 式を使用します。
{error error-message}
ここで、error-message は、Curl コンソールやダイアログ ボックスでユーザーに表示されるメッセージです。たとえば、次のコードはエラーをスローしてメッセージ "The value is zero!" を表示します。
{error "The value is zero!"}

例外の例

次の例では、 NegativeValueException 例外クラスの宣言、例外のスローとキャッチ、およびエラーの生成方法を示します。
注意: 以下のコードのコメントを取り除くと、フェータルエラーがスローされます。
||--        {error e.message}

例: Exception のサブクラスの作成と使用。
|| Create a result box to show warning messages.
{let current-exception:Visual = {text-part}}
{let results:VBox = {VBox}}
{value results}

|| Declare an exception class to signal negative values.
{define-class public NegativeValueException {inherits Exception}
  {constructor public {default message:String}
    {construct-super message}
  }
}

|| Declare a class with a constructor that throws exceptions on bad input.
{define-class public MyClass
  field value:int

  || The initializer takes one argument.
  || If the argument is negative, throw a NegativeValueException.
  {constructor public {default arg:int}
    {if arg < 0 then
        {throw
            {NegativeValueException
                {format "The value %i is negative!", arg}
            }
        }
     else
        set self.value = arg
    }
  }
}

{try
    || Try both positive and negative initial values:
    let var:MyClass = {MyClass -1}
 catch e:NegativeValueException do
    || Uncomment the following line to throw a fatal error
||--         {error e.message}

    || Adds a message to the results area
    {results.add
        "Warning: A NegativeValueException has occurred!"
    }
 catch e:Exception do
    {results.add
        "An unexpected exception has occurred: " & e
    }
 finally
    {results.add "All done."}
}
異なる初期値を使用して、error プロシージャを呼び出したり、ZeroValueException などの新しい例外クラスを作成してこの例を再度実行してみてください。