Dart基本文法まとめ

## はじめに
Flutterを網羅的に学習するにあたって[Roadmap](https://roadmap.sh/flutter)を使って学習を進めることにしました
この記事では、Flutter初学者やこれからFlutterを学習し始める方に向けて、Flutterロードマップの初期段階であるDart Basics(ダート基礎)についてまとめています。

RoadmapはFlutterだけでなく、他の言語やスキルのロードマップも提供されており、何から学習して良いか分からないと悩んでいる方にとって有用なサイトになっています。
ぜひ[Roadmap](https://roadmap.sh/)を利用して学習してみてください。

## Roadmapとは

簡潔に言えば、Roadmap.shは学習者にとっての**ガイドブック**であり、**学習の方向性を提供する学習ロードマップサイト**です。

初心者から上級者まで、ステップバイステップでスキルを習得するための情報が提供されています。

学習の進め方が分かりやすく示されているだけでなく、個々の項目に参考資料やリソースへのリンクも提供されているので、学習者は目標を設定し、自分自身のペースで学習を進めることができます。

## Dart Basics(ダート基礎)
FlutterロードマップDart Basics(ダート基礎)では以下の6つのサイトが紹介されています。
今回は以下のサイトを利用していませんが、興味のある方はぜひお読みください。

- Dart Overview: https://dart.dev/overview
- What is Dart Programming?: https://www.javatpoint.com/flutter-dart-programming
- Dart Tutorial https://www.geeksforgeeks.org/dart-tutorial/
- About Dart https://flutterbyexample.com/lesson/about-dart
- What is Dart? https://www.youtube.com/watch?v=sOSd6G1qXoY
- Dart in 100 Seconds https://www.youtube.com/watch?v=NrO0CJCbYLA

## 1. Dartについて
**Dart**はGoogleが開発したオブジェクト指向[^1]のプログラミング言語です。
主にモバイル、Web、デスクトップ、サーバーアプリケーションの開発に使用されます。

JavaとJavaScriptから多くの特徴を受け継いだ静的型付き[^2]のオブジェクト指向言語ですので、JavaやJavaScriptを以前触ったことがある方は、馴染みやすい言語になっていると思います。
**静的型付け** <=> **動的型付け**[^3]

また、DartではJavaScriptモジュール[^4]を入れることで、ブラウザでのDOM操作[^5]など、JavaScriptが担っていたフロントエンドのプログラミングできるようになります。

## 2. Dartの基礎文法
Dartの基本的な記述法について解説していきます。
Dartでは1つのステートメントごとに、必ず末尾に**セミコロン**(`;`)を付与する必要があります。
セミコロンをつけ忘れると、コンパイルエラーが発生するので、注意してください。
```dart
/// エラー
void main() {
 var hoge = 'hoge'  // セミコロン(;)が付けられていない
 print(hoge);
}

/// 実行される
void main() {
 var hoge = 'hoge';
 print(hoge);
}
```

Dartで**コメント**をするには上記のように、**スラッシュ** (`/`) を2つ重ねます。
スラッシュを2つ重ねた箇所以降はDartコンパイラによってコメントとして認識され、プログラムでの処理対象になりません。

複数行のコメントをするには、スラッシュの次にアスタリクス(`*`)を配置します。
(`*`)がコメントの開始を表します。 コメントの終わりを示すには(`*`)の次にスラッシュを配置します。

```dart
/*
* hoge
* fuga
* foo
* /
```
また、コメントしたい部分を選択して「command + スラッシュ(`/`)」をすることで、選択した部分をコメントアウトすることもできます。

### 1. **変数**
Dartでは`var`を変数名の前に配置して、その次にスペースを空けて変数名を記述することで、変数を定義することができます。
```dart
// ① 初期値なし
var hoge;

// ② 変数の宣言時に初期値を代入することも可能です。
var str = 'Fuga';
```

変数に初期値を定義しなかった場合(上記①など)、デフォルト値はすべて`null`になります。

上記コードをprint文で書くと以下のような結果になります。
```dart
// ① 初期値なし
print(hoge); // null

// ② 変数の宣言時に初期値を代入することも可能です。
print(str); // Fuga
```

#### 1. **型推論**
Dartは静的型付き言語なので、`var`を使用して変数の宣言と代入を同時に行ったときに、型推論が実行され、自動的に変数の型が決定されます。

```dart
var str = 'Fuga';

// is => 指定された型を持っている場合は trueを返します。
print(str is String); // true 
```

変数`str`の初期値はString型(文字列)が与えられているので、型推論によりString型になります。

`var`を使用せずに、変数の型を指定することも可能です。その場合、指定したい型を変数名の前に置き、スペースを空けて変数名を記述します。
```dart
String str = 'Hoge';  // String型
int hoge = 1; // int型
```
#### 2. **再代入**
一度代入した変数に対して、別の値を入れ直すことが可能です。これを**再代入**と言います。
```dart
// int型の変数hogeに対して再代入をしています。
int hoge = 1;
hoge = 2;
hoge = 3;
```

異なる型の値を代入しようとするとエラーが発生します。
```dart
String str = 'Hoge';
str = 2; // String型のstrにint型を代入しようとしているので、エラーが発生する
```

#### 3. **複数の変数**
varに続いてコンマ(`,`)で複数記述することで、変数を一度に宣言することができます。
```dart
var foo, hoge, fuga;

int foo = 1,
hoge = 2,
fuga = 3;
```

### 2. **定数**
定数とは値の変更に制限が加えられている変数のことです。
Dartには2つの定数のタイプがあります。
`const`はコンパイル時に値が代入され、それ以降変更できないのに対して
`final`はプログラムを実行して値が代入されたあと変更できません。

つまり、`const`の方が`final`より制限力が強いということなのです。

#### 1. **final**
finalを付けて宣言された変数は定数として扱われ、後で別の値を代入することができません。
```dart
final int hoge = 1;
hoge = 2 // エラーが発生する

// 型推論を使用した宣言
final hoge = "foo";
print(hoge is String); // true
```

#### 2. **const**
constを使用して宣言された変数はコンパイル時に値が代入され、プログラムの実行時に定数として扱われます。
演算子を使って値の中身を計算する必要がある定数を宣言するときなどに使用します。
```dart
const double arclength = 2 * 3.14 * 4;
const hoge = 'hoge' + 'fuga' + 'foo';
```
両者の違いに対してもっと詳しく知りたい方は[こちら](https://blog.flutteruniv.com/flutter-dart-final-const/)をご覧ください。

### 3. **型**
Dartは**静的型付き言語**ですので、使用できる型の特性を理解することが重要です。

#### 1. **Int型**
整数値を取ることができます。変数の初期値などにint型を指定する場合は、以下の整数リテラル[^6]を使用すると便利です。

- **整数リテラル**
```dart
// 10進数表記
int a = 1;
int b = 2; 
int c = 3;
```

#### 2. **Double型**
浮動小数点数を取ることができます。整数部分を最初に表記して、ドット(`.`)で区切ることで小数部分を表記します。

- **浮動小数点リテラル**
```dart
const double pi = 3.141519;
double y = 1.1;
final z = 2.5424;
```

int、doubleは**num**のサブクラスです。

#### 3. **String型**
文字列を取ることができます。Dartでは**UTF-16**[^7]の文字コードを使用します。シングルクオート(`'`)もしくはダブルクオート(`"`)を使用して文字列リテラルを使用します。
```dart
String str1 = "ダブルクオート";
String str2 = 'シングルクオート';
```
複数行の文字列リテラルはクオートを3つ重ねることで使用できます。
```dart
var str1 = '''
複数行の文字列リテラル
複数行の文字列リテラル
複数行の文字列リテラル
''';

var str2 = """
複数行の文字列リテラル
複数行の文字列リテラル
複数行の文字列リテラル
複数行の文字列リテラル
""";

```

#### 4. **Bool型**
プログラムで真（**True**）または偽（**False**）の２つの値を表現するための型です。
bool型は条件判断や制御フローの判定など、プログラムでさまざまな状況を判断するのに利用されます。真偽の結果によってプログラムの動作を変えることができ、非常に重要なデータ型です。
```dart
var hoge = 2;

if (hoge == 1) {
 // falseと評価され、実行されない 
}
```

#### 5. **List型**
リストは複数のオブジェクトを扱うためのコレクション[^8]の型です。
```dart
const list = const [1, 2, 3, 4, 5, 6] ;

List<String> list = ['Hoge', 'Fuga', 'Foo']; //型指定する場合
```
リストの個別の値を取得するには**インデックスナンバー**を指定します。
```dart
List<int> list = [1, 2, 3];
list[1]; // 2
```
リストの任意の値に対して再代入を実行することも可能です。
```dart
List<String> list = ['Hoge', 'Fuga', 'Foo'];
list[1] = 'one'; // [Hoge, one, Foo]
```

##### 1. **リストの基本メソッド**
リストを操作するにあたって基本的なメソッドがいくつか存在します。

- **リストに新しい値を追加**
```dart
List<int> nums = [1, 2, 3];
nums.add(10); // [1, 2, 3, 10]
```
- **指定した要素に挿入**
```dart
List<String> strings = ['one', 'two', 'three', 'four'];
strings.insert(3, 'insert'); // ['one', 'two', 'three', 'insert', 'four']
```

- **指定した要素を削除**
```dart
List<String> strings = ['one', 'two', 'three', 'four'];
strings.removeAt(3); // ['one', 'two', 'three']
```
- **指定した値がリストの要素として格納されている場合にそのインデックスナンバーを返す**
```dart
List<String> strs = ['Hoge', 'Fuga', 'Foo'];
strs.indexOf('Fuga'); // 1
```
- **要素を比較して昇順に並べる**
関数内にある`a`と`b`は前後する要素の値です。以下の場合だと最初に`a`に1が`b`に9が入ります。**差が負の場合**は、1つ目の要素を2つ目の要素より小さいと判断され、その順序は保持されます。**差が0または正の場合**は、2つ目の要素が1つ目の要素より小さいと判断され、入れ替えられます。例えば、次の`a`に9が`b`に4になったときは、9と4が入れ替わります。
```dart
List<int> nums = [1, 9, 4, 8, 9, 2, 1, 5, 8, 7];
nums.sort(a, b) => a - b); // [1, 1, 2, 4, 5, 7, 8, 8, 9, 9]
```

- **リストの要素をランダムに変更する**
```dart
List<int> nums = [1, 9, 4, 8, 9, 2, 1, 5, 8, 7];
nums.shuffle(); // [8, 9, 2, 5, 9, 1, 8, 4, 7, 1]
```

- **リストの各要素を取り出して、取り出した要素を使った任意の処理**
```dart
int count = 0;
List<int> list = [1, 9, 4, 8, 9, 2, 1, 5, 8, 7];

list.forEach((num) => count += num);
print(count); // 54
```

- **リストの各要素に任意の処理**
`forEach`はリストの要素に直接処理を行うのに対して、`map`はリストの要素を変換して新しいリストを作成します。
```dart
List<int> nums = [1, 2, 3, 4, 5, 6, 7];
nums.map((num) => num * 2); [2, 4, 6, 8, 10, 12, 14]
```

- **リストの各要素を取り出して、bool値を返す**
全ての要素がtrueを返した際は `true`に１つでもfalseが帰ってきた場合は`false`を返します。
```dart
List<int> nums = [1, 2, 3, 4, 5, 6, 7];
nums.every((num) => num % 2 == 0); // false

List<int> nums = [2, 4, 6, 8, 10];
nums.every((num) => num % 2 == 0); // true
```

- **リストの要素を集計する関数を定義する**
```dart
List<int> nums = [1, 2, 3, 4, 5, 6, 7];
nums.reduce((a, b) => a + b); // 28
```

#### 6. **Map型**
複数の値をキーと関連付けて呼び出すための型です。ハッシュマップ、ハッシュテープと呼ばれるデータ構造に対応します。

全ての**キーはユニーク**である必要があるため、重複は許されません。
コンマ(`,`)でペアの集合を区切り、コロン(`:`)でキーとキーに対応する値を決定します。
```dart
// Map<String, String>
var languages = {
 'Python': 'Guido van Rossum',
 'Ruby': 'Matumoto Yukihiro',
 'PHP' : 'Rasmus Lerdorf'
};

// Map<int, String>
var preciousMetals = {
 79: 'gold',
 47: 'silver',
 78: 'platinum'
};

// キーと値の型を指定して宣言する方法 <- Mapの次に<>で最初にキーの型を、次に値の方を指定する
Map<String, String> map = {
 'hoge': 'hoge',
 'fuga': 'fuga'
};
```

- **マップに新しい値を追加する**
マップに対して、新しいキーを指定して、その値を代入することで、マップに新しい値を追加することができる。
```dart
languages['Perl'] = 'Larry Wall';
```

- **マップに格納された値を取り出す**
```dart
languages['Ruby'] // 'Matumoto Yukihiro'
```

- **マップの値を固定する**
```dart
// constを指定することで、変更を防ぐことができる
final preciousMetals = const {
 79: 'gold',
 47: 'silver',
 78: 'platinum'
};
```

##### 1. **マップの基本メソッド**

- **キーを指定して、値と共に削除する**
```dart
var languages = {
 'Python': 'Guido van Rossum',
 'Ruby': 'Matumoto Yukihiro',
 'PHP' : 'Rasmus Lerdorf'
};

languages.remove('PHP'); // {Python: GuidovanRossum, Ruby: MatsumotoYukihiro}
```

- **別のマップを結合する**
```dart
// 2つのマップの型は一致している必要があります
var languages = {
 'Python': 'Guido van Rossum',
 'Ruby': 'Matumoto Yukihiro',
 'PHP' : 'Rasmus Lerdorf'
};

var languages2 = {
 'Perl': 'Larry Wall',
 'C++': 'Bjarne Stroustrap'
};

languages.addAll(languages2); // {Python: GuidovanRossum, Ruby: MatsumotoYukihiro, PHP: RasmusLerdorf, Perl: LarryWall, C++: BjarneStroustrap}
```
- **マップの各要素(キーと値)を順番に取り出して処理を行う**
```dart
var languages = {
 'Python': "Guido van Rossum",
 'Ruby': "Matumoto Yukihiro",
 'PHP' : "Rasmus Lerdorf"
};

String str = "";

languages.forEach((key, value) => str += "<td>" + key + "</td><td>" + value + "</td>");

print(str); //<td>Python</td><td>Guido van Rossum</td><td>Ruby</td><td>Matumoto Yukihiro</td><td>PHP</td><td>Rasmus Lerdorf</td>
```
- **指定したキーが含まれているかの判定**
```dart
var languages = {
 'Python': "Guido van Rossum",
 'Ruby': "Matumoto Yukihiro",
 'PHP' : "Rasmus Lerdorf"
};

languages.containsKey('Ruby'); // true
languages.containsKey('Go'); // false
```

#### **Enum型**
Enum型は定数の宣言やプログラムの設定などで使用する型です。
宣言には**enum**を変数名の前に宣言する必要があります。
```dart
enum Color {red, green, blue}
```
各要素は、互いに識別することができ、インデックスが割り振られています。
Enumの値は別の変数に代入することが可能です。
```dart
var aColor = Color.blue;

switch (aColor) {
 case Color.red: 
  print('Red');
 break;
 case Color.green:
  print('Green');
 break;
 default:
  print(aColor);
}
```

## 3. 関数
### 1. **関数の宣言**
関数を宣言するには**最初に戻り値の型**を指定します。次に関数名を指定して、`()`で仮引数をコンマ区切りで与えます。もし引数を取らない場合は、ここは空にします。
関数の処理の中身はブロック`{}`で与え、戻り値は**return**で指定します。
`return`を呼び出した後は関数の処理は中断され、それ以降の処理は行われません。
```dart
int someFunc(int a) {
 return a * 2;
}

int someFunc2(int a, int b) {
 return a + b;
}

//　戻り値を返さない場合、戻り値の型をvoidを指定する
void someFunc3() {
 print("foo");
}

// 関数の処理が1行で済む場合のみ、アロー関数を使用できる
// アロー関数はブロック({})の代わりにアロー(=>)を使用してこの右側に戻り値を与える

bool isHoge(String str) => str == "hoge";
```

### 2. **関数のパラメータ**

#### 1. **名前付き引数**
関数の宣言の際に`{}`で仮引数を囲んで宣言すると、関数を呼び出す際に`:`を指定して仮引数と関数呼び出すことができるようになります。[名前付き引数](https://qiita.com/akatsukaha/items/497b8990f2a97f64d8d3)を使用することで、引数の指定誤りを防ぐことができます。
```dart
int someFunc4({int one, int two, int three}) {
 return a + b + c;
}

someFunc3(1, 2, 3); // エラー

someFunc3(a: 1, b: 2, c: 3); // 6
```

#### 2. **オプション引数**
引数を`[]`で囲むことでオプション引数を指定することができるようになります。
オプション引数は引数が与えられないときも関数は正常に実行され、値は`null`となります。
```dart
String func(String a, String b, [String c]) {
 var result = a + b;
 if (c != null) {
  result += c;
 }
 return result;
}

func("hello", " "); // "hello "
func("hello", " ", "world"); // "hello world"
```

#### 3. **引数のデフォルト値**
引数の右側に`=`を指定して、引数のデフォルト値を指定することができます。
デフォルト値を設定することができるのは、名前付き引数({})のみです。
仮引数に該当する引数が関数呼び出し時に与えられなかった場合は、デフォルト値が代わりに使用されます。

```dart
int someFunc(int a, {int b = 2}) {
 return a + b;
}

void main() {
 someFunc(1); // 3
 someFunc(1, b: 4); // 5
}
```

#### 4. **main関数**
main関数はアプリケーションを実行した際に最初に実行される特別な関数です。
戻り値は**void**で、引数は空もしくはコマンドラインの入力値を取るListです。
```dart
// test.dart
void main(List<String> args) {
 print(args); // [hoge, fuga]
 print(args.length); // 2
 args.forEach((argv) {
  print(argv); // hoge // fuga
 });
}


dart test.dart hoge fuga
```

### 3. **無名関数(ラムダ関数、クロージャ)**
特定のメソッドの実行結果を**コールバック[^9]形式**で受ける時に使用されます。
```dart
var upper = (str) => print(str.toUpperCase());
var list = ['hoge', 'foo', 'fuga'];

list.forEach(upper); // 'HOGE' 'FOO' 'FUGA'
```

### 4. **ブロック**
Dartはブロックで変数のスコープが分離されるので、名前空間[^10]を使用した名前の管理が簡単になります。
```dart
{
 var a = 1;
 {
  var a = 2;
  print(a); // 2
 }
 print(a); // 1
 {
  print(a); // 1
  var a = 3; 
  print(a); // 3
 }
 print(a); // 1
 {
  print(a); // 1
 }
 print(a); // 1
 {
  print(a); // 1
  var a = 4;
  print(a); // 4
 }
}
```

### 5. **クロージャ**
クロージャは構文上のスコープ内の変数にアクセスすることができる関数であり、オリジナルのスコープから外れていても使用することができます。
```dart
Function curriedFunc(num x) {
 return (num y) => x + y;
}

void main() {
 var hoge = curriedFunc(3);
 var fuga = curriedFunc(5);
 hoge(4); // 7
 fuga(6); // 11

 curriedFunc(4)(5); // 9
}
```

## 4. 演算子
### 1. **算術演算子**
算術演算子は基本的な四則演算を実行するのに使用される演算子です。
```dart
var a = 1 + 2; // 3 加法(＋)
var b = 2 - 1; // 1 減法(−)
var c = -b ; // -1 符号反転(-expr)
var d = 3 * 4; // 12 乗法(*)
var e = 6 / 2; // 3 除法(/)
var f = 10 ~/ 3; // 3 除法 小数点以下切り捨て(~/)
var h = 10 % 3; // 1 剰余 整数の割り算余り(%)
```

前置・後置演算子も用意されています。
```dart
var a = 3;
++a; // 4
var b = 4;
b++; // 5
var c = 5;
--c; // 4
var d = 6;
d--; // 5
```

### 2. **等価・比較演算子**
値の等価性や大小の比較を行うための演算子です。
```dart
1 == 1; // true 左辺と右辺が等しい(==)
2 == 1; // false 
2 != 1; // true 左辺と右辺が等しくない(!=)
2 != 2; // false
3 > 2; // true 左辺が右辺より大きい(>)
2 > 3; // false 
3 < 2; // false 右辺が左辺より大きい(<)
2 < 3; // true
2 >= 3; // false 左辺が右辺より大きいか等しい(>=)
3 <= 2; // false 右辺が左辺より大きいか等しい(<=)
```

### 3. **型演算子**
変数に対して`is`を使用することで、その変数の型とその型が一致しているかをbool型で返します。


| 演算子 | 意味         |
|--------|--------------|
| as     | 型変換を行う (サブタイプの場合)  |
| is     | 型チェック (指定した型と一致するかを検証する)    |
| is!    | 否定型チェック (指定した型と異なっているかを検証する) |

```dart
String hoge = "hoge";

if (hoge is String) {
 print(hoge); // hogeがString型の場合のみ呼び出される
}
```

### 4. **代入演算子**
代入や代入と同時に任意の演算を実行することができます。

| 演算子 | 意味                                    |
|--------|-----------------------------------------|
| =      | 代入                                    |
| -=     | `var -= var2` は `var = var - var2` と同じ      |
| /=     | `var /= var2` は `var = var / var2` と同じ      |
| %=     | `var %= var2` は `var = var % var2` と同じ      |
| +=     | `var += var2` は `var = var + var2` と同じ      |
| *=     | `var *= var2` は `var = var * var2` と同じ      |
| ~/=    | `var ~/= var2` は `var = var ~/ var2` と同じ     |
| <<=    | `var <<= var2` は `var = var << var2` と同じ <br>(ビットを右にシフトする操作)   |
| >>=    | `var >>= var2` は `var = var >> var2` と同じ  <br>(ビットを左にシフトする操作)  |
| ^=     | `var ^= var2` は `var = var ^ var2` と同じ      |
| &=     | `var &= var2` は `var = var & var2` と同じ      |
| \|=      | `var &= var2` は `var = var \| var2` と同じ      |

- **左シフト演算子** (<<)：ビットを左にシフトします。左にシフトすると、数値は2のべき乗倍されます。例えば、x << y は x を y ビットだけ左にシフトします。

- **右シフト演算子** (>>)：ビットを右にシフトします。右にシフトすると、数値は2のべき乗で割られた結果になります。

- **非排他的論理和**（^）:2つの値の対応するビットが等しい場合に1を返し、異なる場合に0を返すビット単位の論理演算です。XOR（排他的論理和）とは逆の振る舞いをします。

- **論理積**（&）:2つの論理値（真または偽）を比較する論理演算です。この演算は、両方の論理値が真（true）の場合にのみ真を返し、それ以外の場合は偽（false）を返します。

- **論理和**（|）:2つの論理値（真または偽）を比較する論理演算です。この演算は、どちらかまたは両方の論理値が真（true）の場合に真を返し、両方の論理値が偽（false）の場合にのみ偽（false）を返します。

### 5. **論理演算子**
複数の等価・比較演算子をつなげて条件分岐の処理を行うときに使用されます。

| 演算子 | 意味                                    |
|--------|-----------------------------------------|
| !expr      | bool型のtrueとfalseを逆転させる |
| \|     | OR  |
| &&     | AND  |

### 6. **その他演算子**

| 演算子 | 名前                   | 意味|
|--------|------------------------|-------|
| ()     | 関数の適用             | 関数の呼び出し時に使用する |
| []     | リストへのアクセス     | リストの特定のインデックスに該当する要素を呼び出す |
| .      | メンバへのアクセス     | オブジェクトのプロパティにアクセスする時に使用する|
| ?.     | 条件付きメンバへのアクセス | プロパティがnullを取る場合に安全にアクセスする<br>ために使用する |

### 7. **三項演算子**
`?`の直前にbool型の戻り値を返す関数や演算を行い、`true`が返ってきた場合には、最初の要素が、`false`が返ってきた場合には次の要素が返ります。
```dart
// 三項演算子を使用することで条件分岐が簡潔になります
var x == 3;
x % 3 == 0 ? 'hoge' : 'fuga';
```

## 5. 構文
### 1. **if -else構文**
条件分岐を行うために使用します。ifに続く`()`の中でbool型の戻り値を与える評価式を記述することで条件分岐を実行する。
```dart
if (isHoge()) {
 print('Hoge');
}
```

ifの後に`else`を記述することで条件が成立しなかった場合の処理を記述することが可能です。
```dart
// isHoge()がtrueを返さなかった場合elseの処理が呼ばれる
if (isHoge()) {
 print('Hoge');
} else {
 print('noHoge');
}
```

2つ以上の条件を指定する場合は`else if()`を指定することで条件式を複数記述できます。
```dart
if (isHoge()) {
 print('Hoge');
} else if(isFoo()) {
 print('foo');
} else {
 print('noHoge');
}
```

### 2. **forループ構文**
```dart
for (var i = 0; i < 5; i++) {
 print(i);
}
// 結果
// 0
// 1
// 2
// 3
// 4
// 5
```

```dart
// Listをループする場合はfor-in構文を使用する
List<String> list = ['foo', 'fuga', 'hoge'];
for (String i in list) {
 print(i);
}
// 結果
// foo
// fuga
// hoge
```

### 3. **while構文**
whileの後に条件式を記述することでループを記述することができます。
```dart
while (isFuga()) {
 print('fuga');
}
```

#### 1. **break文**
whileループの実行途中に`break`が呼び出されるとループが停止される。
無限ループを任意のタイミングで停止するときに使用されます。
```dart
import 'dart:math';

// 0.95以上の数値が出たタイミングで無限ループを停止する
void main() {
 var rng = new Random();
 while(true) {
  var rm = rng.nextDouble();
  if(rm >= 0.95) {
   break;
  } 
  print(rm);
 }
}
```

#### 2. **continue文**
whileの中でcontinueが実行されると、それ以降の文が実行されずに次のループに移行します。

```dart
import 'dart:math';

// 0.1未満の数値が出た場合にその数値を出力せずに次のループに移行する
void main() {
 var rng = new Random();
 while(true) {
  var rm = rng.nextDouble();
  if(rm < 0.1) {
   continue;
  }
  if(rm >= 0.95) {
   break;
  }
  print(rm);
 }
}
```

#### 3. **do-while文**
`do`ブロック内の処理が終わってからwhileの中の処理が実行されます。

```dart
import 'dart:math';

void main() {
 var rng = new Random();
 double rm;

 do {
  rm = rng.nextDouble();
  print(rm);
 } while(rm <= 0.95);
}
```

### 4. **switch文**
ある値に対して複数の候補と等しいかどうかを検証するときに使用します。
switchで与えた引数はcaseで指定した値と等しいかどうかを上から順番に行います。等しい場合はcaseで指定されたブロックの中身の演算が実行されます。
もし、caseで指定されたどの値とも等しくない場合は、defaultの中身が実行されます。

```dart
// case内でbreakが指定されていないと処理が最後まで行われるので、余分な処理を省くためにbreakの記述は必要です。

switch (language) {
 case 'PHP':
  print('PHP');
 break;
 case 'Python':
  print('Python');
 break;
 case 'Ruby';
  print('Ruby');
 break;
 default;
  print('unknown');
}
```

### 5. **assert文**
コードのテストに便利なassert文です。assertで指定した演算結果としてfalseが返されると警告文が出力されます。
```dart
assert(x == 2);
```
`リリースモード`で実行する時にはassertは無視されるため、円滑なテストが可能になります。


>**リリースモード**：プログラムの実行を継続できないエラーが発生しない限り、なるべくエラーを無視してそのまま実行を続けようとします。また、できるだけ速く実行するために、型のチェックなども行われません。
**デバッグモード**：バグの原因と考えられる問題をなるべく早く検出するため、静的な型のチェックだけでなく、動的な方のチェックやassertによるチェックも有効になります。
https://hiyoko-programming.com/1590/


開発時は**デバッグモード**を、リリース時は**リリースモード**を使用します。

### 6. **try-catch-finally文**
例外(Exception)時の処理を書いておかないと、例外が発生した場合にコードが異常終了する恐れがあります。安全なプログラムを記述するには例外を捕捉することが重要です。

#### 1. **例外を発生させる**
例外を発生させるには`throw`という演算子を指定します。
```dart
throw 'Hoge'
new FormatException('Excepted at least 1 section');
```

#### 2. **try-catch**
`try`のスコープ内で発生した例外を捕捉して`catch`のスコープ内で適切な処理を行うことができます。
```dart
// tryで例外が発生した場合は、tryのスコープ内でそれ以降処理は行われません
// 例外のタイプ別に分けるにはonの後に例外の型を指定します。全ての例外を捉えるにはExceptionを指定します。
try {
 someFunc1();
} on OutOfMemoryException {
 someFunc2();
} on Exception catch (e) {
 print(e);
} catch (e) {
 print(e);
}
```

#### 3. **スタックトレース**
スタックトレース[^11]を見るには`catch`に2つ目の引数を指定します。
```dart
try {
 // 処理
} on Exception catch (e) {
 print(e);
} catch (e, s) {
 print(e);
 print(s);
}
```

#### 4. **finally**
例外発生の有無に関わらず必ず実行する処理を記述したい場合は`finally`のスコープ内に処理を記述します。
```dart
try {
 // 処理
} catch (e) {
 print(e);
} finally {
 // 例外発生の有無に関わらず実行される
}
```
## 6. クラス
クラスからオブジェクトを生成するには`new`を使用してコンストラクタを呼び出します。
```dart
var v1 = new Vehicle(120);
```

オブジェクトは関数やメンバを保有しています。メソッドを呼び出すときは、オブジェクトからそれを呼び出します。メソッドはオブジェクトの関数とデータを使用することが可能です。

`.`を使用することでオブジェクトの変数やメソッドにアクセスすることができます。
また、`?.`を代わりに使用することで`null`である可能性のあるプロパティにアクセスするときに例外は発生するのを防ぐことができます。

```dart
var v1 = new Vehicle(120, 1.2);
v1.weigth = 150
```

### 1. **プロパティ**

#### 1. **static変数**
変数の前に`static`を指定することで全てのクラスのインスタンスで共有される変数を宣言することができるようになります。

```dart
class Car {
 static const String brandName = "Toyota";
 // ...
}

var car1 = new Car(150, 1.2);
var car2 = new Car(180, 1.4);

print(car1.brandName); // Toyota
print(car2.brandName); // Toyota
```

### 2. **コンストラクタ**
クラスと同じ名前のメソッドを宣言することでコンストラクタ[^12]を宣言することができるようになります。
コンストラクタはクラスのインスタンスの初期値をリセットするために使用されます。

```dart
class Vehicle {
 num weight, height;

 Vehicle(num weight, num height) {
  this.weight = weight;
  this.height = heigth;
 }
}

// コンストラクタはインスタンスを確保して変数を宣言する時に呼び出されます。
var car1 = new Car(150, 1.2);

print(car1.weight); // 150
print(car1.heigth); // 1.2
```

#### 1. **コンストラクタの継承**
サブクラスはスーパクラスのコンストラクタを呼び出すことはありません。サブクラスで再び新しく宣言し直す必要があります。

### 3. **メソッド**
メソッドはクラスのメンバである関数です。
```dart
class Car extends Vehicle {
 Car(num weight, num height): super(weight, height);

 void beep() {
  print("beep");
 }
}

var car1 = new Car(150, 1.2);
car1.beep(); // beep
```

#### 1. **staticメソッド**
`static`が付与されたメソッドは、インスタンスに対しての直接操作を行うことができません。
代わりにインスタンス化せずに呼び出せるメソッドとして引数をとって演算を行うことが可能です。

```dart
class someClass {
 static void someStaticMethod() {
  // 処理
 }
}

someClass.someStaticMethod(); //　インスタンス化をせずに呼び出せる
```

#### 2. **カスケード表記**
同じインスタンスに対して複数のメソッドを続けて適用したり、特定のプロパティへの代入を繰り返すなど、複数の操作を行う際に使用します。

カスケード表記は、メソッド呼び出しを行う場所で、本来インスタンスが現れるところに、`.`を配置することで利用できます。 つまりカスケード表記は`.`を2つ連続で重ねる形になります。

```dart
// カスケード表記なし
request.response.headers.contentType = new ContentType("text", "plain", charset: "utf-8");
request.response.write("Hello, world");
request.response.close();

// カスケード表記あり
request.response
    ..headers.contentType = new ContentType("text", "plain", charset: "utf-8")
    ..write("Hello, world")
    ..close();
```

### 4. **クラスの継承**
`extends`を使用することでクラスを継承してサブクラスを宣言することができます。
継承元のクラス(スーパークラス)のコンストラクタを呼び出すには`super`を使用します。

```dart
class Vehicle {
 num weight, height;

 Vehicle(num weight, num height) {
  this.weight = weight;
  this.height = height;
 }
}

class Car extends Vehicle {
 Car(num weight, num height): super(weight, height);
 void beep() {
  print("beep");
 }
}
```

#### 1. **メソッドのオーバーライド**
サブクラスからスーパークラスのメソッドを上書き(オーバーライド)して新しくメソッドを定義し直すことが可能です。
メソッドのオーバーライドを行っていることを示すためにメソッドの前に`@override`を追記します。
```dart
class Ambulance extends Car {
 @override 
 void beep() {
  print("whoop");
 }
}
```

#### 2. **noSuchMethod()**
存在しないメソッドを呼び出し場合に呼び出される`noSuchMethod()`をオーバーライドすることが可能です。
```dart
class A {
 @override 
 void noSuchMethod(Invocation invocation) {
  // エラー処理など
 }
}
```

### 5. ジェネリクス
ジェネリクスは総称型とも呼ばれます。
静的型付き言語で、Listなどコンテナ型のオブジェクトに対してメソッドを定義する際に役に立つ機能です。

```dart
bool isAllItemHoge(List<String> hoge) {
 // 処理
}

bool isAllItemHoge(List<num> hoge) {
 // 処理
}

//　ジェネリクスを使用することでListの要素の型ごとに関数を実装する必要がなくなります
bool isAllItemHoge(List<T> hoge) {
 // 処理
}
```


## 参考資料
- [Dart入門-Dartの要点をつかむためのクイックツアー](https://www.amazon.co.jp/Dart%E5%85%A5%E9%96%80-Dart%E3%81%AE%E8%A6%81%E7%82%B9%E3%82%92%E3%81%A4%E3%81%8B%E3%82%80%E3%81%9F%E3%82%81%E3%81%AE%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%83%84%E3%82%A2%E3%83%BC-%E3%83%8A%E3%82%AB%E3%83%8E%E3%83%92%E3%83%88%E3%82%B7-ebook/dp/B07H78C9GR)
- [Flutter入門のためのDart入門](https://qiita.com/teradonburi/items/913fb8c311b9f2bdb1dd)
- [Dart documentation](https://dart.dev/guides)

## 告知
最後にお知らせとなりますが、イーディーエーでは一緒に働くエンジニアを
募集しております。詳しくは採用情報ページをご確認ください。

https://eda-inc.jp/recruit/

みなさまからのご応募をお待ちしております。


[^1]: **オブジェクト指向言語**
「ある役割を持ったモノ」ごとにクラスを分割し、モノとモノとの関係性を定義していくことでシステムを作り上げようとするシステム構成の考え方のこと。
簡潔に言うと「モノ（どんな奴でどう動く）」に注目した考え方のことです。
[こちら](https://wa3.i-3-i.info/word1895.html)にわかりやすい記事があったので、是非読んでみてください。

[^2]: **静的型チェック**
コードの実行前に変数や式の型を検査する仕組みです。
コンパイラや開発環境がコードを解析し、変数や関数の型情報をチェックします。その結果、変数が予期しない型で使用されている場合や、型に関連するエラーや警告が見つかった場合に、開発者に通知されます。
型は必須ですが、型推論のため、型アノテーションはオプションです。

[^3]: **動的型チェック**
コードが実行される際に変数や式の型を検査する仕組みです。
コンパイル時ではなく、実行時に型情報を検査します。変数や式が使用されるたびに、その時点での型情報を確認し、型に関連するエラーや警告を検出します。

[^4]: **モジュール**
プログラムにおいて特定の機能を持ったひとまとまりの構成要素です。
簡潔に言うと、単独でも機能としては成立するけど、普通は他のものと組み合わせて使うような部品のこと
[こちら](https://wa3.i-3-i.info/word12243.html)にわかりやすい記事があったので、是非読んでみていください。

[^5]: **DOM（Document Object Model）操作**
JavaScriptを使用してWebページの要素や構造を変更するための技術です。
Webページは、HTMLで作成されます。DOMを用いることで、HTMLの各要素にアクセスするためのメソッドやプロパティを使用できます。例えば、ユーザーの操作に応じてページの内容や見た目を変更することができます。

[^6]: **整数リテラル**
ソースコードの中に直接べた書きした整数のことです。
[こちら](https://wa3.i-3-i.info/word19041.html)にわかりやすい記事があったので、是非読んでみてください。

[^7]: **UTF-16**
文字コード（文字に割り当てられた数字）の用語のひとつです。もう少し噛み砕いていうと『文字に割り当てた番号』と『実際にコンピュータさんが扱う数字』の対応表のことです。
[こちら](https://wa3.i-3-i.info/word15294.html)にわかりやすい記事があったので、是非読んでみていください。

[^8]: **コレクション**
データやオブジェクトなどをまとめて格納するためのデータ構造やクラスなどの総称のことです。

[^9]: **コールバック**
あるイベントが発生した時に関数の引数として呼び出される関数のことです。
[こちら](https://wa3.i-3-i.info/word12295.html)にわかりやすい記事があったので、是非読んでみてください。

[^10]: **名前空間**
各要素に一意の異なる名前をつけなければ識別できない範囲のことです。
[こちら](https://www.sejuku.net/blog/65850)にわかりやすい記事があったので、是非読んでみてください。

[^11]: **スタックトレース**
実行中のコンピュータプログラムにエラーが発生した際に、直前に実行していた関数やメソッドなどの履歴を表示することです。
[こちら](https://wa3.i-3-i.info/word13281.html)にわかりやすい記事があったので、是非読んでみてください。

[^12]: **コンストラクタ**
インスタンスを作成したタイミングで実行されるメソッドのことです。
(クラスをnewしたタイミングで実行される関数)
最初にやっておかなければならない処理、例えばメンバ変数の初期化処理などによく活用されます。
ただし、コンストラクタには戻り値が返せないという制限もあります。