Skip to content

Instantly share code, notes, and snippets.

@kuredev
Last active May 29, 2022 15:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kuredev/3034b496e378d932ea83c657a2af2fc6 to your computer and use it in GitHub Desktop.
Save kuredev/3034b496e378d932ea83c657a2af2fc6 to your computer and use it in GitHub Desktop.

Dart について

  • Google製
    • 一部ECMAになってる(古い時代の仕様)
  • 型あり(基本静的型付けだけど、動的型付けも可能。型推論もある)
  • 最新Version: 2.17.0
  • インタプリタ(CLI等)とコンパイラ(スマホ用ビルド等)がある
  • 元々はWeb用のスクリプト言語用途で開発、JSにコンパイル可能(2011年~)
  • Flutterに採用されてブレイク
    • 【翻訳記事】なぜFlutterにおいてDartを使用するのか? - Qiita https://qiita.com/yasutaka_ono/items/608405a27e57cc30e0d7
      • 静的言語と動的言語のいいところどり
      • 事前コンパイラもあれば、ホットリロードできるJITもある
      • ウィジェットの定義を書きやすく、XML等のマークアップを必要としなくてよい
      • 高速
  • NULL安全の同梱は 2.12 から(去年の3月)で結構最近

NULL安全について

  • 実行時のNULL参照エラーを防ぐ(コード編集時にIDEやコンパイラが静的分析して検知)ための機能
  • 変数の型に NULL許容と非許容が存在する
    • int a // 非許容
    • int? a // 許容
  • メソッドの引数や戻り値でも指定する

変数の基本の例

void main () {
  int a = 0; // 普通の(NonNullable)
  // int b = null; // Error: The value 'null' can't be assigned to a variable of type 'int' because 'int' is not nullable

  int? c; // Nullable
  c = null;
}

NULLが入る可能性がある処理ではNULL許容にする必要がある例

Dartではハッシュ(Map)で、存在しないキーにアクセスするとNULLになる

Map<String, String> map = {"hoge": "hoge"};
print(map["hoge2"]); // NULL

例えば戻り値にハッシュにアクセスした値が使われる場合、メソッドの戻り値の型はNULL許容にする必要がある

String getMap(String index) {
  Map<String, String> map = {"hoge": "hoge"};

  // ★以下でエラー
  return map[index]; // A value of type 'String?' can't be returned from the function 'getMap' because it has a return type of 'String'
}

以下のように String? にすればOK

String? getMap(String index) {
  Map<String, String> map = {"hoge": "hoge"};
  return map[index];
}

NULL非許容にする方法(NULLでは無い保証を入れる。例:Null-aware演算子(??)を使う)

String getMap(String index) {
  Map<String, String> map = {"hoge": "hoge"};
  return map[index] ?? ""; 
}

クラスになるとまた一つややこしい

NULL非許容なインスタンス変数は初期化しないと問答無用でエラーになる。 例えば以下はだめ。

// インスタンス変数は初期化しないと駄目
// Non-nullable instance field 'name' must be initialized
class Kure {
 String name;

 Kure(); // これはコンストラクタ(何もしない)
}

こうするとか

class Kure {
 String name = "";

 Kure();
}

こうする(コンストラクタの引数で初期化)

class Kure {
 String name;

 Kure(this.name);
}

Kure ca = Kure("hoge"); 

でもこの書き方だと駄目(どうやらインスタンス変数が初期化されなかった、とみなされるらしい)

// ★エラー
// Non-nullable instance field 'name' must be initialized.
class Kure {
 String name;

 Kure() {
   this.name = name;
 };
}

ただし、「NULL非許容だけど、初期化は後でやるから見逃して」を許容する書き方もある( late を付ける)

class Kure {
 late String name; // これならエラーにならない

 Kure();
}

静的解析の抜け穴?も

論理的には null は帰らないが、静的解析ではそこまで理解されないパターン

// ★エラー
// int? にしないとエラーになる
int getNumber(){
  int j = 0;

  if (j == 0){
    return 1;
  }else{
    return null; // Error: The value 'null' can't be returned from a function with return type 'int' because 'int' is not nullable.
  }
}

所感

  • メリット
    • 多分最大のメリットは「常にNULLが入りうるかを意識する」ようになること
    • NULLがありうるかをコードで表現できるし抜け漏れが出にくい(コメントに書かなくていい)
  • デメリット
    • 単純に書く量が増えて面倒

関連リンク

Sound null safety | Dart https://dart.dev/null-safety

Flutter2.0 Sound Null Safety とは? – ギャップロ https://gaprot.jp/2021/04/27/flutter-sound-null-safety/amp/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment