LoginSignup
8
6

More than 5 years have passed since last update.

Dartではtrue以外はfalseとして振る舞う

Posted at

JavaScriptでは様々な値が真偽値として特徴的な振る舞いを見せます。

falseとして振る舞う値

  • undefined
  • null
  • false
  • -0, 0, NaN
  • ""

trueとして振る舞う値

  • true
  • -0, 0, NaN以外のnumber
  • ""以外のstring
  • その他のオブジェクト

これらはif文で活用することで読みやすくも読みにくくもなる面白いテクニックですが、同様のことをDartでも検証してみました。

undefined

Dartにはそもそもundefinedという値はありません。また、未定義のシンボルを呼びだそうとすると実行時エラーとなりますので、undefinedについては真偽値が得られません。

  /// NoSuchMethodError: method not found 'get:obj'
  test("undefined", () {
    if (obj) {
      expect(true, isFalse);
    } else {
      expect(false, isFalse);
   }
  });

面白いのは、objという名前の変数がないとき、objのgetterがないというエラーになることですね。

null

nullに関してはJavaScriptと同様の振る舞いを見せました。これは直感的なので違和感もないですね。

  /// Passed : null => false
  test("null", () {
    var obj;
    if (obj) {
      expect(true, isFalse);
    } else {
      expect(false, isFalse);
    }
  });

number

numberはすべての場合においてfalseとして振る舞いました。

  group("number", () {
    /// Passed : 0 => false
    test("0", () {
      if (0) {
        expect(true, isFalse);
      } else {
        expect(false, isFalse);
      }
    });
    /// Passed : -0 => false
    test("-0", () {
      if (-0) {
        expect(true, isFalse);
      } else {
        expect(false, isFalse);
      }
    });
    /// Failed : -1 => false
    test("-1", () {
      if (-1) {
        expect(true, isTrue);
      } else {
        expect(false, isTrue);
      }
    });
    /// Failed : 1 => false
    test("1", () {
      if (1) {
        expect(true, isTrue);
      } else {
        expect(false, isTrue);
      }
    });
    /// Passed : NaN => false
    test("NaN", () {
      if (double.NAN) {
        expect(true, isFalse);
      } else {
        expect(false, isFalse);
      }
    });
  });

string

stringにおいても、すべての場合でfalseとして振る舞いました。

  group("string", () {
    /// Passed : "" => false
    test("empty", () {
      if ("") {
        expect(true, isFalse);
      } else {
        expect(false, isFalse);
      }
    });
    /// Failed : "true" => false
    test("true string", () {
      if ("true") {
        expect(true, isTrue);
      } else {
        expect(false, isTrue);
      }
    });
  });

その他のオブジェクト

その他のオブジェクトに関してもすべてfalseの振る舞いになりました。

  group("object", () {
    /// Passed : {} => false
    test("empty object", () {
      if ({
      }) {
        expect(true, isFalse);
      } else {
        expect(false, isFalse);
      }
    });
    /// Failed : object => false
    test("not empty object", () {
      if ({
          "name" : "laco",
          "flag" : false
      }) {
        expect(true, isTrue);
      } else {
        expect(false, isTrue);
      }
    });
  });

まとめ

Dartでtrueとして振る舞う値

  • true

Dartでfalseとして振る舞う値

  • その他すべて

ということになりました。さすが型安全というべきでしょう。感動しました。今回の調査に使ったソースコードを最後に添付しておきます。実行は$ dart object_as_bool_test.dartです。

ちなみに、dartの実行時に$ dart --checked object_as_bool_test.dartとすると、boolean以外を真偽値として扱おうとしている事自体がエラーとなってテストがすべてエラー落ちします。use structみたいなものですね。

object_as_bool_test.dart
import 'package:unittest/unittest.dart';

main() {

  /// NoSuchMethodError: method not found 'get:obj'
  test("undefined", () {
    if (obj) {
      expect(true, isFalse);
    } else {
      expect(false, isFalse);
    }
  });
  /// Passed : null => false
  test("null", () {
    var obj;
    if (obj) {
      expect(true, isFalse);
    } else {
      expect(false, isFalse);
    }
  });
  group("number", () {
    /// Passed : 0 => false
    test("0", () {
      if (0) {
        expect(true, isFalse);
      } else {
        expect(false, isFalse);
      }
    });
    /// Passed : -0 => false
    test("-0", () {
      if (-0) {
        expect(true, isFalse);
      } else {
        expect(false, isFalse);
      }
    });
    /// Failed : -1 => false
    test("-1", () {
      if (-1) {
        expect(true, isTrue);
      } else {
        expect(false, isTrue);
      }
    });
    /// Failed : 1 => false
    test("1", () {
      if (1) {
        expect(true, isTrue);
      } else {
        expect(false, isTrue);
      }
    });
    /// Passed : NaN => false
    test("NaN", () {
      if (double.NAN) {
        expect(true, isFalse);
      } else {
        expect(false, isFalse);
      }
    });
  });
  group("string", () {
    /// Passed : "" => false
    test("empty", () {
      if ("") {
        expect(true, isFalse);
      } else {
        expect(false, isFalse);
      }
    });
    /// Failed : "true" => false
    test("true string", () {
      if ("true") {
        expect(true, isTrue);
      } else {
        expect(false, isTrue);
      }
    });
  });
  group("object", () {
    /// Passed : {} => false
    test("empty object", () {
      if ({
      }) {
        expect(true, isFalse);
      } else {
        expect(false, isFalse);
      }
    });
    /// Failed : object => false
    test("not empty object", () {
      if ({
          "name" : "laco",
          "flag" : false
      }) {
        expect(true, isTrue);
      } else {
        expect(false, isTrue);
      }
    });
  });
}
8
6
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
8
6