LoginSignup
55
33

More than 5 years have passed since last update.

Dartの例外処理と裏ワザ(?)

Last updated at Posted at 2014-07-15

例外の発生

例外を投げるにはthrow構文を用います。最も単純な形は以下のようにErrorオブジェクトを投げるコードです。

class Door {

  bool locked;

  Door(this.locked);

  void openDoor() {
    if (locked) {
      throw new Error();
    }
  }
}


void main() {
  var lockedDoor = new Door(true);
  lockedDoor.openDoor();
}

これを実行すると以下のようにエラーが出ます。

Unhandled exception:
Instance of 'Error'

『インスタンスの状態が原因である』エラーを投げるにはStateErrorを使います。

  void openDoor() {
    if (locked) {
      throw new StateError("the door is locked");
    }
  }
Unhandled exception:
Bad state: the door is locked

Errorを継承している組み込みの例外用クラスは他にもAbstractClassInstantiationError, ArgumentError, AssertionError, CastError, ConcurrentModificationError, CyclicInitializationError, etc...と、とても多いので、こちらのAPIドキュメントを見つつお好みの例外を探し当ててください。

もしくは、自分でErrorクラスを継承してオリジナルのErrorを作ってもいいと思います。

class DoorLockedError extends StateError {
  DoorLockedError() : super("door is locked");
}

例外を処理する

例外の処理にはいろんな言語でお馴染みのtrycatchfinallyを使います。

例外のメッセージだけ欲しい場合

もっとも単純な形はこちら。

void main() {
  var lockedDoor = new Door(true);
  try {
    lockedDoor.openDoor();
  } catch(e) {
    print(e); //Bad state: the door is locked
  }
}

メッセージとスタックトレースが欲しい場合

一緒にスタックトレースも欲しい場合は次のように書きます。

void main() {
  var lockedDoor = new Door(true);
  try {
    lockedDoor.openDoor();
  } catch(e, stackTrace) {
    print(e); //Bad state: the door is locked
    print(stackTrace); //スタックトレース
  }
}

例外の種類ごとに処理を変えたい場合

発生した例外の種類ごとに特別な処理がしたい場合は以下のon構文を用います。

void main() {
  var lockedDoor = new Door(true);
  try {
    lockedDoor.openDoor();
  } on StateError catch(e) {
    print(e);
  } on NoSuchMethodError catch(e) {
    print(e);
  } catch(e) {
    print(e);
  }
}

例外が発生したということだけ知りたい場合

例外の型を指定したとき、例外情報が必要ない場合はcatch部分を省くことが出来ます。

void main() {
  var lockedDoor = new Door(true);
  try {
    lockedDoor.of();
  } on StateError{
    print("StateError");
  } on NoSuchMethodError{
    print("NoSuchMethodError");
  } catch(e) {
    print(e);
  }
}

上のコードはWebStormで書くと赤線表示されますが正常に動作します。どうもDartプラグインがon構文周りにあまり対応してないようで補完も効かないです。今後に期待です

finally文

当然finally文で必ず実行させたい終了処理を書くことが出来ます。

void main() {
  var lockedDoor = new Door(true);
  try {
    lockedDoor.openDoor();
  } catch(e) {
    print(e);
  } finally{
    print("finish");
  }
}

裏ワザ(?)

ところでなぜDartのcatch文は

catch(Error e){

ではなく

catch(e){

なのでしょうか?一番最初に挙げたErrorクラスのオブジェクトを投げて例外を発生させるコードの実行結果をよく見ると、

Unhandled exception:
Instance of 'Error'

と書かれていますね。そして、StateErrorクラスだと

Unhandled exception:
Bad state: the door is locked

です。2行目のメッセージはprint(e)で出力されたものですから、つまり

print(e.toString());

となっているわけです。

何が言いたいかというと、catch文は実は

catch(Object e){

なのです。 『nullでない全てのオブジェクトがthrowできる』 という機能の結果として、catch文に入ってくる例外はObject型になっています。すなわち、以下のコードが正常に動作します。

void throwError() {
  throw new DateTime.now();
}

void main() {
  try {
    throwError();
  } catch(e) {
    print(e); //2014-07-15 19:48:02.032
  }
}

あらゆるオブジェクトをthrowできるというのは面白い機能だと思います。使いどころは余り思いつきませんが覚えておくといつか役に立つかもしれません。

55
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
55
33