Closed7

Flutter & Dart Cookbookの読書メモ(第2章)

marbullmarbull

chapter 2

Exploring Control Flow

制御フローは、アプリケーションにおける命令の実行方法に関連する。
典型的なロジックフローとして、条件付きフロー、ループフローなどがあり、命令の処理順序を決定するために使用される。

Dartは、この決定フローに基づいて、アプリケーションがどのようにオペレートし、調整するかを管理するための方法を数多く提供している。

PythonやJavacriptなど、他の言語を使ったことがある方なら、この章で扱う内容はよくご存知でしょう。初めて開発に携わる方にとって、この章は非常に重要である。
制御フロー文は、ほとんどの言語において共通。
ある言語を習得するためには、このようなステートメントを取り入れる能力が必要。

この章では、制御フローを使用してアプリケーションにロジックを組み込む方法について学ぶ。
また、各文章の使用例も紹介する。多くのフローには、どのようなアクションを取るかを指示するために使用する条件文が含まれている。
これらの条件に特に注意し、アプリケーションで制御フローを効率的に使用するようにする。

marbullmarbull

2.1 Verifying That a Condition Has Been Met

  • Problem
    命令を実行する前に、条件の論理チェックを行いたい。
  • Solution
    バイナリーオプションの制御文に if 文を使用する。
    if文は、論理文が有効であることを確認するためのステップを提供する。
    複数のオプションがある場合は、switch 文の使用を検討する。
    この例では、if 条件の使用方法を説明する。if 文は、bool 変数の値をチェックするために使用する。
    bool変数がtrueに設定されている場合、最初のメッセージが表示される。
    bool変数がfalseに設定されている場合、別のメッセージが表示される。
void main() {
  bool isFootball = true;

  if (isFootball) {
    print('Go Football !!');
  } else {
    print('Go Sports !!');
  }
}
  • Discussion
    if文を使用すると、アプリケーション内のロジックの進行を制御することができる。
    この種の制御フローは、アプリケーションを構築する上で不可欠であり、選択肢を選択するための簡単なメカニズムを提供する。
    この例では、if文の検証は暗黙的に行われる。
    つまり、代入された値が真であることをチェックしている。
    論理演算子である&&や||も、テストする式を拡張するために使用することができる。
    AND 演算子を使用して、コードを実行する前に両方の式が真であることを検証する。
    論理 OR は、1 つまたは複数の式が真であるかどうかを確認するために使用し、各式は順番に評価される。さらに、論理演算子は、ブール値に対して !演算子を使用することで反転させることができる。
    if文の典型的な使用例は、2つ以上の選択肢の中から選択すること。2つしか選択肢がない場合、このタイプの制御フローは理想的。
    また、「collection if」は、要素をテストするための追加機能を提供する。コレクションオブジェクトの条件(例えば、データ構造の最初のオブジェクトか最後のオブジェクトか)に基づいて、その要素に関連するデータを設定することができる。
marbullmarbull

2.2 Iterating Until a Condition Is Met

  • Problem
    アプリケーションの中で、ある条件が満たされるまでループするメソッドを作りたい。
  • Solution
    制御フローの開始時に入力条件を検証する必要がある場合は、whileループを使用する。
    注意:ループチェックは、ループ条件の開始時に行われる。従って、whileループの反復回数は最小0回、最大N回となる。
    whileループの制御フローの例は以下。
void main() {
  bool isTrue = true;

  while (isTrue) {
    print('Hello');
    isTrue = false;
  }
}

do whileループは、ループを最低1回実行させる必要がある場合に使用する。
ループの条件は入力時にチェックされる。つまり、このループ構成は各反復の前に検証されることになる。
以下は、do whileループの制御フロー例。

void main() {
  bool isTrue = true;

  do {
    print('Hello');
    isTrue = false;
  } while (isTrue);
}

この制御構造では、条件は文の最後で検証され、ループは少なくとも1回実行されることを意味する。

  • Discussion
    これらの例から観察される重要なニュアンスは、実行の性質と、それが制御フローの処理に何を意味するかということ。
    whileループの例では、bool変数がtrueに設定されたときのみ、デモアプリケーションは値を出力する。
    do while ループの例では、isTrue 変数の初期値に関係なく print 文が出力される。
    whileループは、ループを実行する前に条件をテストするので、0〜N回の繰り返しに使用できる。
    典型的な使用例としては、実行される反復処理の回数を制御するために変数を使用するものがある。
    do while文の場合、典型的な使用例は、少なくとも1回のループの繰り返しがある場合である。
    もし、1回の反復が必要な状況であれば、このような制御フローを使用することは良い選択である。
marbullmarbull

2.3 Iterating over a Range of Items

  • Problem
    定義された範囲の項目をループするメソッドが欲しい。
  • Solution
    for文を使って、定義された範囲内で定義された回数の繰り返しを行う。具体的な範囲は、for文の初期化の一部として決定される。
    以下は、for文の例。
void main() {
  int maxIterations = 10;
  for (var i = 0; i < maxIterations; i++) {
    print('Iteration: $i');
  }
}

また、ループでアクセスできるオブジェクト(イテラブル)がある場合は、forEachを使用することもできる。

void main() {
  List daysOfWeek = ['Sunday', 'Monday', 'Tuesday'];

  daysOfWeek.forEach((print));
}
  • Discussion
    for文は、ある動作を正確な回数だけ実行する(例:変数の初期化)など、さまざまなユースケースに使用することができる。
    whileループと同様に、入力時に条件を確認し、条件を満たした場合にループを終了する。
    条件を満たさない場合は、項目の範囲を使い切るまでループを継続する。
    2つ目の例で示したように、forEach文は、オブジェクト内の情報にアクセスするのに非常に便利な手法。
    反復可能な型(例えば、Listオブジェクト)がある場合、forEach文は、コンテンツに直接アクセスする能力を提供する。
    List オブジェクトに forEach を追加すると、リスト内の各項目に直接 print 文を割り当てることができるようになり、ショートカットが可能になる。
    for文の典型的な使用例は、ある範囲が定義されている場合に反復処理を行うこと。
    また、Listや類似のデータ型を効率的に処理する場合にも使用できる。
marbullmarbull

2.4 Performing Conditional Actions Based on a Value

  • Problem
    提示された値に対して、複数の論理チェックを行いたい。
  • Solution
    複数のロジックステートメントがある場合は、switch文を使用する。
    一般的に、複数の論理チェックが必要な場合、最初に思いつく制御フローはif文かもしれない。
    しかし、switchステートメントを使用した方が効率的な場合がある。
    以下はswitch文の例。
void main() {
  int myValue = 2;

  switch(myValue) {
    case 1: print('Monday');
      break;
    case 2: print('Tuesday');
      break;
    default:
      print('Error: value not defined?');
      break;
  }
}
  • Discussion
    switch(またはcase)文は、複数の条件を処理するための改良されたif文である。
    case文はif文と同じように動作するが、チェックする条件が複数あることが特徴。
    case文は、2つ以上の条件を確認する場合、より読みやすいif文として使用できる。
    switch(またはcase)文は、複数の条件を処理するための改良されたif文。
    case文はif文と同じように動作するが、チェックする条件が複数あることが特徴。
    case文は、2つ以上の条件を確認する場合、より読みやすいif文として使用できる。
    複数の条件がどのように有効であるかを見てみる。
    switch文は、複数のif文よりも可読性が高い。論理的な条件を検証する必要がある場合、switch文の方が文体的にすっきりしていることがある。
    この例では、switch文の有効な選択肢は1か2の2つ。このコードを拡張して、もっと多くの選択肢を取り入れることができる。
    switch文は、関連する値が追加されていない場合、デフォルトの文をレンダリングする。つまり、他の選択肢はデフォルトのオプションに送られ、クリーンアップセクションとして機能する。
    明示的なステートメントを取り入れることは、情報の処理におけるエラーを減らすのに有効。
marbullmarbull

2.5 Using an Enumerator to Represent Values

  • Problem
    アプリケーション内で使用する定数値をグループ化して定義したい。
  • Solution
    enum (列挙) を使用して、関連するデータの一貫したモデルである情報のグループ化を提供する。
    以下は、enumに関連する値を宣言し、出力する例。
enum Day { sun, mon, tues }

void main() {
  print('${Day.values}');
}

以下は、0番目のenumの参照を宣言し、出力する例。

enum Day { sun, mon, tues }

void main() {
  print('${Day.values[0]}');
}

以下は、values.byNameの使用例。

enum Day { sun, mon, tues }

void main() {
  print('${Day.values.byName('mon')}');
}

上記の例は、Dartでコードを書く際の列挙型の多用途性を示している。
執筆時点では Dart はトップレベルのスコープでの enum 定義しかサポートしていない。
つまり、クラスや関数の内部で定義を移動することができない。
enum(またはenumeration)は、関連する項目を定義するために使用される。
enumは、例えば、曜日や月などの順序付けられたコレクションと考えることができる。
この例では、1ヶ月目は1月、12ヶ月目は12月というように、順序を値で置き換えることができる。
最初の例では、enumを使用して一連の値を出力する方法を示している。
一般的にenumはデータアクセス全体を簡略化することができる。
enumの中の特定の要素が必要な場合、2番目の例に示すように、これを実現することも可能。
3番目の例では、enumの値に数値インデックスでアクセスするのではなく、DartはbyNameメソッドを追加している。
このメソッドを使用すると、enum 値に関連付けられた名前を使用して簡単にデータにアクセスすることができる。
printコマンドを実行すると、デバッグ出力にenumに関連付けられた値、つまり "mon "が表示される。enumはまだインデックス化されていますが、各項目の位置に応じた数値ではなく、より便利な方法でアクセスすることができるようになった。

marbullmarbull

2.6 Implementing Exception Handling

  • Problem
    アプリケーション内でエラー処理を行う方法を提供したい。
  • Solution
    Dartで例外管理を行うには、try、catch、finallyブロックを使用する。
    以下は、Dartで例外を処理する方法の例。
void main() {
  String name = "Dart";

  try{
    print('Name: $name');
    // The following line generates a RangeError
    name.indexOf(name[0], name.length - (name.length + 2));
  } on RangeError catch(exception) {
     print('On Exception: $exception');
  }
  catch(exception) {
    print('Catch Exception: $exception');
  } finally {
    print('Mission completed!');
  }
}
  • Discussion
    サンプルコードでは、関連するセクションを定義し、"Dart "という単語を格納するStringを設定する。
    4つのメモリスロットに基づくString変数の割り当てを行っている。
    例外を発生させるために、indexOfメソッドを無効な範囲(String変数の長さより大きいもの)を使用。Stringに割り当てられたメモリの最後の項目を越えて移動すると、RangeError例外が生成される。
    この例では、indexに指定された範囲が、宣言された変数に対して無効であることを示している。
    tryブロックは、コードの通常の処理に使用される。コードのブロックは、何か異常が発生していることを示すイベントが発生するまで実行され続ける。一般的には、例外を捕捉するためにコードをtryブロックに配置する。
    onブロックは、発生した特定の種類の例外を処理するために使用される。
    この例では、RangeErrorが発生することが予想される。
    catchブロックは、異常なイベントが発生した場合の一般的な処理を行うために使用される。
    catchブロックを使用すると、発生したイベントを安全に回復または処理する機会を提供できる。
    ほとんどの場合、発生した例外の種類を事前に特定することはできない。
    catchブロックを使用すると、エラーが発生したときにコードが優雅な方法で反応するようになる。
    finallyブロックは、コードが正常に実行されたか例外が発生したかに関係なく、実行されるべきアクションを実行するために使用される。
    一般的に、finallyブロックは、開いているファイルを閉じるなどのクリーンアップに使用されます。
    また、例外が発生しても、処理が完了したことを示すメッセージを出力する。
    例外処理は確かに制御フローの一種であるが、伝統的な意味での例外処理ではない。
    例外処理を追加することは、アプリケーションが複雑になるにつれて、ますます重要になる。
このスクラップは2023/02/10にクローズされました