【Dart入門】基礎文法

## はじめに
Dartの基礎文法を学んだので記事にしたいと思います。

## 開発環境
Dart SDK 2.10.0

## 型推論
Dartは型を推論できます。
型が決まらないことを明示するためにdynamic型があります。SwiftのAny型みたいなイメージですね。

## 変数
変数のデフォルト値は**null**です。

``` dart
int i;  // i is null
```

**final**キーワードをつけると変更不可になります。

``` dart
final str1 = "型推論なし";
final String str2 = "型推論あり";
```

**const**キーワードをつけるとコンパイル定数となります。
コンパイル定数とは、その定数を利用している箇所がコンパイル時に低数値に書き換わる定数のことです。
finalはプログラム実行時に初期化され、constはコンパイル時に初期化されます。

## Built-in型
Built-in型とは、最初から用意されている型のことです。
DartのBuilt-in型は下記の通りです。

* int, double
* String
* bool
* List
* Set
* Map
* Runes
* Symbol


### int, double

intは整数、doubleは浮動小数点です。
intとdoubleのどちらかが入る場合は、**num**で宣言できます。

``` dart
  final int i = 10;
  final double d = 3.14;
  final num n1 = 10;
  final num n2 = 3.14;
```


### String

文字列型です。シングルクオートダブルクオートどちらもでも生成でき、**${}**でテンプレートリテラルを使用できます。

``` dart
  final String str1 = 'aiueo';
  final String str2 = 'str is :${str1} ';
  print(str2); // str is :aiueo 
```

また、**'''**にすると複数行の文字列を生成できます。

``` dart
  final String str3 = '''
  一行目
  二行目
  ''';
  print(str3);
```

**r**をシングルクォーテーションもしくはダブルクォーテーションの前につけるとraw文字列になります。

``` dart
  final String rawStr = r'アイウエオ\nかきくけこ';
  print(rawStr); // アイウエオ\nかきくけこ
```

### bool
真偽値です。trueとfalseどちらもコンパイル定数です。

### List
コレクションクラスです。値の追加、代入は下記の通りです。

``` dart
  List<int> list = [];
  list.add(10);
  list.add(20);
  list[1] = 21;
  print(list); // [10, 21]
```

初期化方法は下記の通りです。

``` dart
  List<int> list1 = [];
  var list2 = <int>[];
  var list3 = List<int>();
```

複数このリストを初期化したい場合はこのようになります。

``` dart
  var list = new List.generate(10, (i)=> i);
  print(list); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```

### Set
Setは値が一意なコレクションクラスです。Setクラスは**LinkedHashSet**クラスがデフォルト実装になっているので、順序を保持しています。
初期化は下記のようになります。

``` dart
  Set<int> s1 = {};
  Set s2 = {};
```

値が一意になるので、同じ要素を追加した場合は重複しません。

``` dart
  Set<int> s1 = {};
  s1.add(1);
  s1.add(1);
  s1.add(2);
  print(s1);  // {1, 2}
```

### Map
Mapはkey-valueの連想配列です。
Mapクラスのデフォルト実装は、**LinkedHash**クラスです。

``` dart
  Map map = Map<String, int>();
  map['a'] = 100;
  map['b'] = 200;
  print(map);  // {a: 100, b: 200}
```

### Runes
Runesは文字列内で32ビットUnicode値を表現するためのクラスです。
Dartの文字列はUTF-16コード単位の並びであるので、32ビットのUnicode値を文字列内で表現するにはRuneクラスを使用します。

``` dart
  final String clapping = '\u{1f44f}';
  print(clapping);
  print(clapping.codeUnits);
  print(clapping.runes.toList());

  Runes input = new Runes(
      '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
  print(new String.fromCharCodes(input));
```

### Symbol
Symbolは名前つき引数を指定する場合などに使います。

``` dart
  var function1 = (String first, {String second, String third}) {
    print(first + second + third);  // abc
  };
  Function.apply(function1, ["a"], {#second: "b", #third: "c"});
```

## アクセス修飾子
Dartにはprivate、publicなどの可視性のキーワードはありません。
クラス名、変数名、関数名が**_(アンスコ)**で始まる場合はプライベートを意味しています。

``` dart
class _PrivateClass {   // private class
  int _i;               // private property
  void _privateFunc() { // private function
  }
}
```

## 関数
基本的な形は下記のようになります。

``` dart 
戻り値の型 関数名(引数の型 引数名) {
 return 戻り値;
}
``` 

下記は具体的な関数の定義と呼び出しです。

``` dart
void main() {
  sampleFunction("サンプル");  // sample サンプル
}

void sampleFunction(String str) {
  print('sample ${str}');
}
```

また下記のようにシンタックスシュガーを用いて、**=>**を使って書くこともできます。

``` dart
bool isEnable(int i) => i == 1;
```


### 名前付き引数
下記のように**{}**で囲った引数は呼び出し側で引数名を指定することになります。
またこの引数は任意指定となります。

``` dart 
void main() {
  sampleFunction(argument1: 10, argument2: "hoge"); // 10 hoge
  sampleFunction();                                 // null null
}

void sampleFunction({int argument1, String argument2}) {
  print(argument1);
  print(argument2);
}
```

**@required**アノテーションをつけると必須引数になります。

``` dart 
void main() {
  sampleFunction(argument1: 10, argument2: "hoge"); // 10 hoge
  sampleFunction();                                 // 呼び出せない
}

void sampleFunction({@required int argument1, @required String argument2}) {
  print(argument1);
  print(argument2);
}
```

### オプショナルパラメーター
引数に**[]**をつけるとオプショナルの引数になり、非必須となります。

``` dart
void main() {
  sampleFunction(10);            // 10 null
  sampleFunction(10, "aiueo");   // 10 aiueo
}

void sampleFunction(int argument1, [String argument2]) {
  print(argument1);
  print(argument2);
}

```

## クロージャ
クロージャは下記のように書きます。

``` dart
void main() {
  final add1 = closure(2);
  print(add1(10));          // 12
}

Function closure(int addNumber) {
  return (int i) => i + addNumber;
}
```

## クラス
下記に、フィールド、コンストラクタ、ゲッター、セッター、メソッドを定義したサンプルのクラスを定義します。

``` dart 
void main() {
  final SampleClass sampleClass = SampleClass("けんたろう", 10);
  sampleClass.message = "よろしくお願いいたします。";
  sampleClass.hello(); // 私の名前はけんたろうです。 歳は10才です。 よろしくお願いいたします。
}

class SampleClass {
  // フィールド
  final String name;
  final int age;
  String _message;
  
  // コンストラクタ
  SampleClass(this.name, this.age);
  
  // ゲッター
  String get message => this._message;
  
  // セッター
  set message(String message) => this._message = '私の名前は${this.name}です。 歳は${this.age}才です。 ${message}';
  
  // メソッド
  void hello() {
    print(this._message);
  }
}
```

## Enum
DartのEnumの定義は下記のように書きます。

``` dart
enum Color { red, green, blue }
```

各値にはindexプロパティがあり、宣言順の値が取得できます。

``` dart
void main() {
  print(Color.red.index);            // 0
}
```

**values**プロパティを使用すると、Enumで定義した全ての値を取得できます。

``` dart
void main() {
  print(Color.values);               // [Color.red, Color.green, Color.blue]
}
```
**switch**文で条件分けするときには、全ての値を条件に入れないと警告が出ます。
その代わり**default**キーワードが不要になります。


``` dart
void main() {
  final Color color = Color.red;
  switch (color) {
    case Color.red:
      print("red");                  // red
      break;
    case Color.green:
      print("green");
      break;
    case Color.blue:
      print("blue");
      break;
  }
}
```

## typedef
typedefを使用すると、関数型に別の名前をつけることができます。

``` dart
typedef Typedef = String Function(int i);

void main() {
  final Typedef t = (int i) => 'argument: ${i}';
  print(t(10)); // argument: 10                                
}
```