Dart2基本構文と機能のメモ

## はじめに
自分が忘れないようにするためのメモの趣向がつよいです。
ゆっくりメンテしていきます。
編集リクエスト歓迎です。

本当はlanguage-tourに日本語版又はリポジトリがあればそれの和訳とかやりたかったんですが無さそうだったのでこんな感じでメモっていこうかなと。

## 参考資料
https://www.dartlang.org/guides/language/language-tour

## サンプルコードリスト
https://github.com/k-okina/practice-dart

### 全てがObject
### const 編

```dart
void main() {
  const List<int> b = [1,2,3]; // OK(const値)
  // b[0] = 4; // コンパイルエラー(指す先も変更不可)
  List<int> c = b;
  // c[0] = 4; // コンパイルエラー(指す先も変更不可)
  c = [2,3,4];
  print(c);
}
```

### final編

```dart
void main() {
  final List<int> b = [1,2,3]; // OK
  b[0] = 4; // コンパイルエラーにならない
  // b = [1, 2, 3]; // コンパイルエラーになる
}
```

### constとfinalの違い
finalはキーワードを付与した変数は再代入禁止になるが、その変数が束縛している先は再代入を許可する。
jsのconstと挙動は同じ。
constは束縛している先も再代入を許可しない。
jsのObject.freezeを付けてくれる感じ。

### コンパイル時定数(compile time constant)
まぁこんな感じ。
リテラルを固めてくれる

```dart
void main() {
  List<int> b = const [1,2,3];
  // b[0] = 4; // コンパイルエラー(指す先も変更不可)
  b = [1,2,3]; // OK
}
```

### listの挙動その1
まぁここまではjsと同じ

```dart
void main() {
  List<int> a = [1,2,3];
  List<int> b = a;
  List<int> c = new List<int>.from(b);
  b[1] = 3939;
  c[1] = 4649;
  print(a); // [1, 3939, 3]
  print(b); // [1, 3939, 3]
  print(c); // [1, 4649, 3]
}
```

### map

正常系

```dart
void main() {
  // String -> int
  const Map<String, dynamic>map = {
    'value': 'fuga',
    'child': {
      'value': 3939,
      'child': {
        'value': 4649
      }
    }
  };

  print(map); // {value: fuga, child: {value: 3939, child: {value: 4649}}}
  print(map['fuga']); // null
  print(map['value']); // 'fuga'
  print(map['child']); // {value: 3939, child: {value: 4649}}
  // mapのvalueをdynamicにしないと、childのchildにたどり着けない。(型推論の影響
  print(map['child']['child']); // {value: 4649}
  print(map['child']['child']['value']); // 4649
}
```

異常系

型推論弱い。
リテラルで与えてるんだからもうちょっと頑張って欲しいけど型推論はTypescriptとかの方が全然強そう。

```dart
void main() {
  // String -> int
  const map = const {
    'value': 'fuga',
    'child': {
      'value': 3939,
      'child': {
        'value': 4649
      }
    }
  };

  // The method '[]' isn't defined for the class 'dart.core::Object'.
  print(map['child']['child']);
}
```

### Symbol
こんな感じ.
\# prefiではじめるそう。
JSのSymbolとは別物の模様。
もちろんSymbolクラスから生成もできる

```dart
void main() {
  Symbol hoge = #helloworld;
  print(hoge == #helloworld); // true
  print(hoge == #helloworld2); // false

  Symbol fuga = new Symbol('helloworld');
  print(hoge == fuga); // true
  print(fuga == new Symbol('helloworld')); // true
}
```

### 関数
関数。
アロー演算子みたいなのも使えるみたい。

```dart
void main() {
  int a(int a) => a * a;
  Function b(int b) => (int c) => b * c;
  Function c = (int d) => d * d;

  print(a(10)); // 100
  print(b(10)(20)); // 200
  print(c(200)); // 40000
}
```

この辺もjsライク

```dart
int stock = 0;
int add(int value) {
  stock += value;
  return stock;
}

void main() {
  const a = 1000;
  int b(int c) {
    return a + c;
  }
  print(b(10)); // 1010
  print(add(10)); // 10
  print(add(10)); // 20
}

```

## cli

### 良い感じに分解してくれる

```dart
void main(List<String> args) {
  // $ dart print_args 1 2 3 4 hello world
  // ってやると
  // [1, 2, 3, 4, hello, world]
  // って出力される
  print(args);
}
```

### 攻撃の耐性もある
どこまで攻撃耐性あるのかわからないけどこの程度のは自動で防いでくれた

```dart
void main(List<String> args) {
  // $ dart print_args2.dart $hello
  // []
  // $ dart print_args2.dart ${hello}
  // []
  // $ dart print_args2.dart hoge${hello}
  // [hoge]

  const hello = 'hogehoge';
  print(args);
}
```

### 型キャスト

正常例

```dart
void main() {
  // String -> int
  int one = int.parse('1');
  print(one); // 1

  // String -> double
  double onePointOne = double.parse('1.1');
  print(onePointOne); // 1.1

  // String -> double -> int
  double number = double.parse('123.6');
  print(number.round()); // 123
  print(number.round() is int); // true
  print(1.0 is double); // true
  print(1.0 == 1.000000); // true
  print(1.0 == 1); // true
  print('1' == 1); // false

  // int -> String
  String oneAsString = 1.toString();
  print(oneAsString); // 1

  String piAsString = 3.14159.toStringAsFixed(2);
  // 小数点2桁まで保持にしてるの
  print(piAsString); // 3.14
}
```

異常例

```dart
void main() {
  // FormatException: Invalid radix-10 number
  int.parse('123.6');
  // FormatException: Invalid radix-10 number
  int.parse('123hello');
}
```

## assert

--enable-assertsオプションを付けた際にassertにtrueが渡らなかった場合その時点でエラーを吐いてプログラムを停止してくれる。
--enable-assertsがついてなかったら(本番時とか)assertは無視される。
ちなみにflutterの場合開発モードだと常に--enable-assertsがついてる模様。

```bash
$ dart --enable-asserts assert.dart
```

```dart:assert.dart
void main() {
  // String -> int
  int one = int.parse('1');

  // Failed assertion: line 4 pos 10: 'one == 2': is not true.
  assert(one == 2);

  // Failed assertion: line 7 pos 10: 'false': is not true.
  assert(false);
}
```