連載
» 2008年07月10日 00時00分 公開

Flashの基礎を無料で習得! ActionScript入門(7):移ろいやすいユーザーの心をつかむためのエラー処理 (2/3)

[吉村美保,クラスメソッド株式会社]

ランタイムエラーはなぜ起きたのか

 さて、あらためて先ほどのランタイムエラーはなぜ起きたのかというのを説明します。

 Soundクラスのcloseメソッドの用途は「サウンドの読み込みを中止する」というものなのですが、コードを見て分かるように、そもそも一度も読み込みを行っていないので、エラーが起きています。しかし、構文的には問題がないので、こういったケースはコンパイルエラーとしては検出されません。実行時にcloseメソッドの中でサウンドの読み込みを行っていないことが分かり、そこで初めてエラーが起きます。エラーはFlash Playerに通知され、先ほどのエラーダイアログが表示されていたわけです。

エラーをなくすには?

 では、Lesson7_1.asのtestメソッド内を次のように変更して実行してみましょう。

Lesson7_1.as(testメソッド内変更)
    private function test():void {
        var mySound:Sound = new Sound();

        try {
            mySound.close();
        } catch (error:Error) {

        }

    
}

 今度はエラーが表示されなくなりましたね。try-catchがあることで、発生したエラーがcatchステートメントで処理され、Flash Playerには通知されなくなります。

図4 try-catchがある場合とない場合 図4 try-catchがある場合とない場合

catchステートメントの中で、エラーの内容を画面に表示させるには?

 ただこれだけでは、エラーを無視したのと同じことなので、catchステートメントの中で、エラーの内容を画面に表示させるように変更してみましょう。

Lesson7_1.as(testメソッド内変更)
    private function test():void {
        var mySound:Sound = new Sound();
        try {
            mySound.close();
        } catch (error:Error) {

            var errorText:TextField = new TextField();
            errorText.width = 600;
            errorText.text = error.message;
            addChild(errorText);
        
}
    
}

 実行してみましょう。

図5 Lesson7_1.as(testメソッド内変更)の実行結果 図5 Lesson7_1.as(testメソッド内変更)の実行結果

 「Error #2029: この URLStream オブジェクトには開いているストリームがありません。」と表示されました。エラーが発生すると、エラーオブジェクトが生成され、「catch(error:Error)」にあるerrorにエラーオブジェクトが格納されるようになっています。そして、コード中の、「errorText.text = error.message;」で、テキストフィールドにerrorオブジェクトのmessageプロパティを代入し、エラー内容を画面に表示しています。

 今回はエラー内容を表示するだけでしたが、エラー処理を使えば、例えばエラーの発生時に代替処理を行ったり、正しい操作方法をメッセージとしてユーザーに伝えることもできると思います。

 いかかでしょうか。エラー処理の必要性を多少ご理解いただけたでしょうか。

エラーを投げる?

 さて、「エラーが起きた」という状況をFlash Playerはどのように認識しているのでしょうか。そこでは「throw」というキーワードが重要になってきます。

 エラーが起きたことをFlash Playerに通知させるには、エラーをスローすることが必要です。一般的には、以下のようなコードを書きます。

throw new Error("I am an Error");

 このコードは、「Errorクラスのオブジェクトを生成し、Flash Playerに向けて投げる」という意味です。「I am an Error」という文字列はErrorオブジェクトのmessageプロパティに格納されます。先ほどのSoundクラスのcloseメソッド内でも、読み込みを中止するべきサウンドストリームがなかったときに、このthrow句を使って、エラーを投げています。

 例えば、先ほどのコードを変更してSoundクラスのcloseメソッドを使わずに、throw句を使ってエラー処理をしてみましょう。クラス名はLesson7_2としました。

Lesson7_2.as
package {

//import文は省略

public class Lesson7_2 extends Sprite {
    public function Lesson7_2() {
        test();
    }

    private function test():void {
        try {
            throw new Error("Catch me!");
        } catch (error:Error) {
            var errorText:TextField = new TextField();
            errorText.width = 600;
            errorText.text = error.message;
            addChild(errorText);
        }
    }
}
}

図6 Lesson7_2.asの実行結果 図6 Lesson7_2.asの実行結果

 先ほどと同じように処理できましたね。

エラーのクラスには、どんな種類があるのかな?

 先ほどから何回か出てきたErrorクラスですが、一体どんなクラスかというのも説明したいと思います。Errorクラスはエラーをスローするために使用されるクラスです。一般的にcatchステートメントの引数には、Errorクラスかそのサブクラスを指定します。

 Errorクラスには、「ECMAScriptコアErrorクラス」「ActionScriptコアErrorクラス」「flash.errorパッケージErrorクラス」があります。簡単にですがそれぞれの説明をしたいと思います。

  • ECMAScriptコアErrorクラス
    ECMAScript(ECMA-262)Edition4言語仕様案で規定されているクラス
  • ActionScriptコアErrorクラス
    ActionScriptに特有のエラー条件やエラー処理機能に関するクラス
  • flash.errorパッケージErrorクラス
    Flash Playerに特有のエラーイベントを伝達するためのクラス

 Errorクラスのサブクラスにもいろいろな種類がありますので、一部紹介します。

  • ArgumentErrorクラス
    メソッドで指定された引数がそのメソッドの定義に適合しない場合にスローされるエラー
  • TypeErrorクラス
    数値の値が許容される範囲内に収まらない場合にスローされるエラー
  • IOErrorクラス
    入出力エラー。例えば、未接続のソケットに対して読み書き操作を実行した場合にスローされるエラー
  • SecurityErrorクラス
    セキュリティエラー。例えば、セキュリティの面で許可されていないURLにアクセスしようとした場合にスローされるエラー
  • ScriptTimeoutErrorクラス
    スクリプトのタイムアウト間隔である15秒が経過した場合にスローされるエラー

エラー処理では、1つのcatchしか実行されない

 Errorには、さまざまなサブクラスがあることにもつながる話なのですが、エラー処理にはcatchステートメントを複数記述できます。例えば、以下のようなコードを書いたとします。

try {
    // エラーが発生する可能性のある処理
} catch (error:ArgumentError) {
    // ArgumentErrorがスローされた際の処理
} catch (error:Error) {
    // そのほかのエラーがスローされた際の処理
}

 このようなコードを書くと、ArgumentErrorがスローされた場合は1つ目のcatchステートメントが実行されます。それ以外のエラーがスローされた場合は、2つ目のcatchステートメントが実行されます。こうすることでエラーに対しての処理分けができます。しかし、ここで注意が必要なのが、各catchステートメントは上から順にチェックされ、スローされたエラーに該当するcatchステートメントが1つだけ実行されるということです。

 上から順なので、例えば、先にErrorクラスのcatchステートメントを記述してしまうと、ArgumentErrorがスローされていたとしてもArgumentErrorはErrorクラスのサブクラスなので、Errorクラスのcatchステートメントの処理のみが行われます。それを確かめるために、以下のコードを入力してみましょう。

Lesson7_3.as
package {

//import文は省略

public class Lesson7_3 extends Sprite {
    public function Lesson7_3() {
        test();
    }

    private function test():void {
        try {
            throw new ArgumentError();               【1】
        } catch (error:Error) {                      【2】
            createTextField("Error");
        } catch (error:ArgumentError) {               【3】
            createTextField("ArgumentError");
        }
    }

    private function createTextField(message:String):void {
        var errorText:TextField = new TextField();
        errorText.width = 600;
        errorText.text = message;
        addChild(errorText);
    }
}
}

図7 Lesson7_3.asの実行結果 図7 Lesson7_3.asの実行結果
  • 【1】ArgumentErrorをthrow
  • 【2】Errorクラスのcatchステートメント
  • 【3】ArgumentErrorクラスのcatchステートメント

 実行すると、図7のように【2】の処理は実行されていますが、【3】の処理は実行されていないのが分かると思います。記述の順番を間違えないようにしましょう。

 次ページでは、エラーのイベントについて解説し、カスタムエラークラスを作成します。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。