###### tags: `lang` `ref` # Dart 文法チートシート ## 変数・定数 ```dart // 変数(・定数)定義 var foo = fun(); final bar = fun(); // 再代入不可 late baz = time_consuming_process(); // baz が参照されるまで、 time_consuming_process() は実行されない const hoge = 100; // コンパイル時定数 final fuga = const []; // fuga.add(20) のように追加もできない // 型指定 int? foo = null; // var キーワードがないが、var である late String bar; final bar = []; // List<dynamic> になる final baz = <int>[]; // List<int> になる final List<int> hoge = []; // List<int> になる ``` ## 型 ```dart // 組み込み型 int a = 1; double b = 2.5; String c = "test"; bool d = false; List<int> e = [1, 2, 3, 4]; Set<int> f = {1, 2, 3, 3}; Map<String, int> g = {"a": 1, "b": 2}; int? h = 123; // nullable な変数を定義できる int i = h!; // ! を使って non-null にキャストできる。もし、h が null だったら例外が飛ぶ // any 型 (以下の 2 パターンがある) // - Object?: コンパイル時に型チェックされる // - dynamic: 実行時に型チェックされる List<Object?> j = [1, "2", 3.0, null]; List<dynamic> k = [1, "2", 3.0, null]; // キャスト num l = 256; // num は int と double の super type double m = l as double; // as キーワードでキャストできる (supertype -> subtype のキャストは OK! subtype -> supertype のキャストは NG!) int n = l as int; // typedef typedef IntList = List<int>; IntList o = [1, 2, 3]; ``` ## 制御構文 ```dart // if 文 const num = 500; if (num % 2 == 0) { print("even"); } else { print("odd"); } // for 文 for (int i = 0; i < 10; i++) { print(i); } for (var c in "test".split("")) { print(c); } // while 文 while (!game.done()) { game.advance(); } // switch 文 var command = "RUN"; switch (command) { case "RUN": player.run(); case "WAIT": player.run(); default: throw 'Unknown command'; } // try-catch-finally 文 try { something(); } catch on OutOfMemoryException { handleOutOfMemoryException(); } catch (e, s) { // catch (e) でも可 print("$s"); rethrow; } finally { print("done"); } ``` ## 関数 ```dart // エントリポイント void main() { print("Hello World\n"); } // エントリポイント(コマンドライン引数を取るとき) void main(List<String> args) { for (final arg in args) { print(arg); } } // 関数は first-class object int doubleNum(int n) { return 2 * n; } var l = [1, 2, 3, 4]; print(l.map(doubleNum)); // 匿名関数 print(l.map((n) => 2 * n)); print(l.map((int n) { return 2 * n; })); /* 引数の定義方法 - required positional parameters - named parameters - optional positional parameters */ void func1(int a, int b, {required int c, int? d, int e = 123}) {} void func2(int a, int b, [int? c, int d = 123]) {} func1(1, 2, c: 3); func1(1, 2, c: 3, d: 4, e: 5); func2(1, 2, 3); func2(1, 2, 3, 4); ``` ## クラス ```dart /* - enum - abstract classによるインターフェース定義・実装 - mixin - メソッドのオーバーライド - 名前付きコンストラクタ - ジェネリクス - 継承 */ import 'dart:math'; enum Gender { Male, Female, Other, } // - T はジェネリクスの型パラメータ // - Dart には interface 構文がない。インターフェースを定義したい場合は abstract class を使う abstract class Authenticatable<T> { bool attempt(T credential); } mixin PhoneHolder { String? phoneNumber; void call() { if (this.phoneNumber != null) { print("call ${this.phoneNumber}!"); } } } // - with: mixin 時に使う // - implements: インターフェースの実装時に使う // - extends: 継承時に使う class Person with PhoneHolder implements Authenticatable<String> { String name; String pass; Gender gender; // コンストラクタ Person(this.name, this.pass, this.gender); // 名前付きコンストラクタ Person.Male(String name, String pass) : this(name, pass, Gender.Male); Person.Female(String name, String pass) : this(name, pass, Gender.Female); Person.Other(String name, String pass) : this(name, pass, Gender.Other); @override String toString() { return "name=${this.name} gender=${this.gender}"; } // Authenticatable<String> インターフェースの実装 bool attempt(String credential) { return credential == pass; } } class Student extends Person { static int _nStudents = 0; String id; Student(this.id, String name, String pass, Gender gender) : super(name, pass, gender) { Student._nStudents++; } static get nStudents => Student._nStudents; } ``` ```dart /* - const コンストラクタ - 演算子のオーバーロード */ class Rectangle { final int x, y; // const コンストラクタ const Rectangle({required this.x, required this.y}); // 演算子のオーバーロード Rectangle operator *(int scale) => Rectangle(x: scale * this.x, y: scale * this.y); @override String toString() => "x=${this.x} y=${this.y}"; } class Square extends Rectangle { // コンストラクタ内で例外を投げているので、このコンストラクタは const にできない Square({required int x, required int y}) : super(x: x, y: y) { if (x != y) { throw "is not square. need x=y, but got ${this}"; } } } ``` ## ジェネレータ ```dart Iterable<int> range(int n) sync { var i = 0; while (i < n) { yield i; i += 1; } } ``` ## 非同期処理 ```dart import 'dart:io'; import 'dart:convert'; Future<String> getURLContent(String url) async { final client = HttpClient(); final request = await client.getUrl(Uri.parse(url)); final response = await request.close(); final result = await utf8.decodeStream(response); client.close(); return result; } Future<void> main() async { final result = await getURLContent("https://example.com"); print(result); } ```