Flutter(Dart)の基礎知識(定数・関数・ループ)

Flutterを扱うにあたって、Dart言語を使用しないといけません。今回は文法の定数や制御文、関数などの使用方法を記事にしていきたいと思います。その前に、本編にも出てくる**静的**や**動的**についておさらいですが、最初から最後まで存在し続けるオブジェクト(クラスやインスタンス)を`「静的」`と呼び、プログラム実行中に生成されたり、破棄されるオブジェクトのことを`「動的」`と呼ぶので理解しておいて下さい。
##定数(final, const)とstatic定義
###final
```dart
final int hogeA = 0; // finalが指定された変数は一回だけプログラム開始後に初期化され、その後は再代入することができません。
hogeA = 1; // Error表示となり再代入できません。
final int hogeA = 1; // またこのような名前が被る再宣言も無効です。
```

```dart
final List<int> hogeB = [1,2,3,4]; //　指定された変数の配列の内容は変更される。
hogeB[0] = 5; // => [5,2,3,4] 0番目が5に書き換わる。
```
###const

```dart
const int hogeC = 0; // 変数の値がコンパイル時に確定してプログラム実行時に初期化されるので、再宣言・再代入・メモリ領域内容における変更が不可能。
```

```dart
const List<int> hogeD = [1,2,3,4]; // => [1,2,3,4]
hogeD[0] = 5; // => Error表示
```
###static

```dart
class Hoge {
  static int hoge1 = 1;
  static var hoge2;
  static final int hoge3 = 3; // 静的変数を定数にする為にfinalやconst修飾子を使用します。
  static const int hoge4 = 4;
  static void hoge() { // voidは空の型の表現(returnが無いので値を渡さずただ処理するだけに使用)
    print('hogehoge'); // プロパティのメソッドをインスタンス化せずしようすることが可能。
  } // クラスのプロパティを静的にするにはこのstatic修飾子を使用
} 

void main() {
  print(Hoge.hoge1); // => 1
  print(Hoge.hoge2); // => null
  print(Hoge.hoge3); // => 3
  print(Hoge.hoge4); // => 4
  Hoge.hoge(); // => hogehoge
}
```

##制御文(if, for, for in, forEach, while, do while)
###if文(if, else if, &&, ||, !=, switch, 三項演算子などの条件分岐)

```dart
main() {
  var value = 4; // 初期の値

  if (value % 2 == 0) { 
    print('2の倍数'); 
  } else if (value % 4 == 0) {
    print('4の倍数');
  } else if (value % 8 == 0) {
    print('8の倍数');
  } else {
    print('2, 4, 8の倍数以外');
  }
}
// if (条件式1) {
//  条件式1が真の時に実行する処理;
// }else if(条件式2) {
//  条件式1が偽で条件式2が真の時に実行する処理;
// }else if(条件式3) {
//  条件式1及び条件式2が偽で条件式3が真の時に実行する処理;
// }else{
//  全ての条件式が偽の時に実行する処理;
// }
// 上記の式で実行すると => 2の倍数　が出力されます。
// ifの中の条件には、true、falseしか入らないので、nullや文字列を入れないように。
```

```dart
main() {
  var value = 19; // どの条件式にも当てはまらない数字

  if (value % 2 == 0) { 
    print('2の倍数'); 
  } else if (value % 4 == 0) {
    print('4の倍数');
  } else if (value % 8 == 0) {
    print('8の倍数');
  } else {
    print('2, 4, 8の倍数以外');
  }
} // => 2, 4, 8の倍数以外
```

```dart
main() {
  var value = 8; // 論理演算子を使用「&&」は、２つの条件が両方ともtrueの場合

  if (value % 2 == 0 && value % 3 == 0) {
    print('2と3の倍数');
  } else if (value % 2 == 0) {
    print('2の倍数');
  } else if (value % 3 == 0) {
    print('3の倍数');
  } else {
    print('2, 3の倍数以外');
  }
// => 2の倍数
```

```dart
main() {
  var value = 8; // 「||」は、どちらか一方の条件がtrueの場合

  if (value % 2 == 0 || value % 3 == 0) {
    print('2か、3の倍数');
  } else {
    print('2と3の倍数以外');
  }
  // => 2か、3の倍数
```

```dart
main() {
  var value = 3; // 「!」は条件の否定

  if (value % 2 != 0) {
    print('2の倍数以外');
  }
  // => 2の倍数以外
```

```dart
main() {
  String fruit = 'fish'; // switchは式の評価(値)が3つ以上に枝分かれする際の条件分岐に使用
  switch (fruit) {
    case 'meat':
      print('肉');
      break;
    case 'fish':
      print('魚');
      break;
    case 'salad':
      print('サラダ');
      break;
    default:
      print('肉、魚、サラダ、以外');
      break;
  }
} // => 魚

//switch(条件式){
//  case 値A:
//    (実行したい処理)
//    break;
//  case 値B:
//    (実行したい処理)
//    break;
//  case 値C:
//    (実行したい処理)
//    break;
//  default:
//    (実行したい処理)
//    break;　　
//}
```

```dart
main() {
  var age = 20;　// if文でのロジック
  var drink = '';
  if (age >= 20) {
    drink = '酒';
  } else {
    drink = 'ジュース';
  }
  print(drink);
  // 酒

main() {
  var age = 20;　// 三項演算子でのロジック
  var drink = '';
    drink = (age >= 20) ? '酒' : 'ジュース';
  print(drink);
  // 酒
```
###for文(繰り返し)

```dart
main() {
  List<int> hogeList = [1, 2, 3, 4];

  for (int i = 0; i < hogeList.length; i++) {
    print(hogeList[i]);
  }
} // => 1  2  3  4
```
###for in文(オブジェクトの各プロパティに対し繰り返し)

```dart
main() {
  List<int> hogeList = [1, 2, 3, 4];

  for (var value in hogeList) {
    print(value); // 配列や中身の値を順不同で処理
  }
} // => 1  2  3  4
```
###forEach文(配列やコレクションに対して繰り返し)

```dart
main() {
  List<int> hogeList = [1, 2, 3, 4];
  Map hogeMap = {
    1: 'first',
    2: 'second',
    3: 'third',
    4: 'fourth',
  };
  hogeList.forEach((int value) {
    print(value);
  }); // => 1  2  3  4
  var hogeSet = {'first', 'second', 'third', 'fourth'};
  hogeSet.forEach((value) {
    print(value);
  }); // => first  second  third  fourth
  hogeMap.forEach((key, value) {
    print('$key : $value');
  }); // => 1:  first  2:  second  3:  third  4:  fourth
} // 指定したコレクション(データの集合)から要素をひとつずつ取り出して文を実行。
```
###while文(与えられた条件を満たしている場合繰り返し)

```dart
main() {
  List<int> hogeList = [1, 2, 3, 4];
  var index = 0; // 処理の実行前に判断
  while (true) {
    if (index >= hogeList.length) {
      break;
    }
    print(hogeList[index]);
    index++;
  }
} // => 1  2  3  4
```
###do while文(条件式の評価が最後に行われる繰り返し)

```dart
main() {
  List<int> hogeList = [1, 2, 3, 4];
  var index = 0; // 処理の実行後に判断(パスワードの処理など)
  do {
    print(hogeList[index]);
    index++;
  } while (index < hogeList.length);
} // => 1  2  3  4
```

##関数(名前付き関数, 無名関数, 戻り値(return))
関数は２種類の`void型関数(戻り値のない関数)`と`「戻り値のある関数」`に分けられます。

・名前つき関数(named function)
・無名関数(anonymous function)※コールバック関数に使用。

戻り値とは、関数の処理を終えた後に呼び出し元に返すvalue(データ)のことです。呼び出し元に値を返すことを「return」といい、返す値を「戻り値」といいます。

関数を定義するにあたって、外部のvalue(データ)**引数**を関数に渡すことで、渡した引数を関数内で使用することができます。この引数を渡す前の段階(関数を定義するときに)使う`仮の引数`の事を**パラメータ**といいます。

###void型関数(パラメータ無し, パラメータ有り)

```dart
main() {
  call(); //ここで関数の呼び出し(パラメータなし)　 
}

void call() {
  print('hogehoge'); // void 関数名(){(実行したい処理)}
} // => hogehoge
```

```dart
main() {
  add(3, 6); //ここで関数の呼び出し(パラメータあり)　 
}

void add(int hoge1, int hoge2) {
  int hogeTotal = hoge1 + hoge2;
  print(hogeTotal); // void 関数名(parameter){(実行したい処理)}
} // => 9
// (　)の中に関数で使用するパラメータを宣言します。関数名がadd、パラメータがhoge1,hoge2として関数内で変数のように定義します。
```

###戻り値がある関数(パラメータ無し, パラメータ有り)

```dart
main() {
  String hoge = call(); //ここで関数の呼び出し(パラメータなし)
  print(hoge); // 戻り値のある関数を定義するには、関数名の前に戻り値の型を宣言し、戻り値を指定するために、戻り値の前に「return」を宣言
}

String call() {
  return 'hogehoge';
} // => hogehoge

// (定義)
// 戻り値の型 関数名(){
// 　（実行したい処理）
//   return 戻り値;
// }

// (関数の呼び出し方 & 戻り値の受け取り方)
// 戻り値の型 オブジェクト名 = 関数名();
```

```dart
main() {
  int hogeTotal = add(3, 6); //ここで関数の呼び出し(パラメータあり)
  print(hogeTotal);
}

int add(int hoge1, int hoge2) {
  int hogeTotal = hoge1 + hoge2;
  return hogeTotal;
} // => 9

// (定義)
// 戻り値の型 関数名(パラメータ) {
// 　（実行したい処理）
//   return 戻り値;
// }

// (関数の呼び出し方 & 戻り値の受け取り方)
// 戻り値の型 オブジェクト名 = 関数名(引数);
```

###キーワード引数がある関数
キーワード引数とはvalue単体を関数に渡す代わりに「パラメータと引数をセット」で渡す引数のことをいい、関数に利用することで、引数の順序を変えたり、パラメータに初期値を与えたりできます。キーワード引数を使用するには、パラメータを{　}で囲みNULL許容型のチェックもします。

```dart
main() {
  add(hoge1: 3, hoge2: 6);
  add(hoge2: 9, hoge1: 12);
}

// パラメーターを中括弧で囲むと、名前付きパラメーターになるだけでなく、オプションになります.
// そのためNull許容型としてnull値も代入できるようにint型の後ろに?をつけます。
// さらに、null許容型ではない名前付き引数には、デフォルトを設定するか、新しいrequiredキーワードでマークを付ける必要があります。
void add({int? hoge1, required int hoge2}) {
  int hogeTotal = hoge1! + hoge2; // null checkとして!を入れて下さい。
  print(hogeTotal);
} // => 9 21

//(定義)
//戻り値の型 関数名({パラメータ}) {
//　（実行したい処理）
//}

//(キーワード引数の関数の呼び出し方)
//関数名(パラメータ:引数);
```
キーワード引数で、初期値を指定するには「=」でパラメータに初期値を代入します。パラメータに初期値を指定する場合はNULL許容は必要ありません。初期値が指定されたパラメータは関数を呼び出す際、引数を渡さなくても実行できます。引数を渡さなかった場合、パラメータで指定した初期値が関数で使用されて、渡した場合は引数の値が関数で使用されます。

```dart
main() {
  add(hoge1: 3); //hoge1=3, hoge2=2
  add(hoge2: 6); //hoge1=1, hoge2=6
  add(); //hoge1=1, hoge2=2
}

void add({int hoge1 = 1, int hoge2 = 2}) {
  int hogeTotal = hoge1 + hoge2;
  print(hogeTotal);
} // => 5  7  3

//(定義)
// 戻り値の型 関数名({パラメータ = 初期値}) {
// 　（実行したい処理）
// }
```

###アロー関数(=>)
関数で定義したいコードを１行でまとめられる際に使用。{　}の中に実行したいコードを書かず「=>」の後に実行したいコードを定義。戻り値を返すのに「return」を宣言する必要なし。(NULL許容型)

```dart
main() {
  call();
  int hogeTotal = add(hoge1: 3, hoge2: 9);
  print(hogeTotal);
}

void call() => print('hogehoge');
int add({int? hoge1, required int hoge2}) => hoge1! + hoge2;

// (void型)
// void 関数名() => 実行したい処理;

// (戻り値のある場合)
// 戻り値の型 関数名() => 実行したい処理;
```