分岐
このページでは、分岐を使用してDartコードのフローを制御する方法を示します。
- if文と要素
- if-case文と要素
- switch文と式
Dartでは、以下の方法でも制御フローを操作できます。
if
#Dartは、オプションのelse節を持つif文をサポートしています。ifの後の括弧内の条件は、ブール値に評価される式である必要があります。
if (isRaining()) {
  you.bringRainCoat();
} else if (isSnowing()) {
  you.wearJacket();
} else {
  car.putTopDown();
}式コンテキストでのifの使用方法については、条件式を参照してください。
if-case
#Dartのif文は、case節の後にパターンが続くことをサポートしています。
if (pair case [int x, int y]) return Point(x, y);パターンが値と一致した場合、パターンが定義する変数がスコープ内で使用可能な状態で、その分岐が実行されます。
前の例では、リストパターン[int x, int y]が値pairと一致するため、パターンが定義した変数xとyがスコープ内で使用可能な状態で、分岐return Point(x, y)が実行されます。
それ以外の場合は、制御フローがelse分岐に進み、存在する場合は実行されます。
if (pair case [int x, int y]) {
  print('Was coordinate array $x,$y');
} else {
  throw FormatException('Invalid coordinates.');
}if-case文は、単一のパターンに対してマッチングおよびデストラクチャリングを行う方法を提供します。複数のパターンに対して値をテストするには、switchを使用します。
switch文
#switch文は、値の式を一連のcaseに対して評価します。各case節は、マッチングする値のパターンです。caseにはあらゆる種類のパターンを使用できます。
値がcaseのパターンと一致すると、caseの本体が実行されます。空でないcase節は、完了後にswitchの末尾にジャンプします。break文は必要ありません。空でないcase節を終了するその他の有効な方法には、continue、throw、またはreturn文があります。
case節が一致しない場合にコードを実行するには、defaultまたはワイルドカード_節を使用します。
var command = 'OPEN';
switch (command) {
  case 'CLOSED':
    executeClosed();
  case 'PENDING':
    executePending();
  case 'APPROVED':
    executeApproved();
  case 'DENIED':
    executeDenied();
  case 'OPEN':
    executeOpen();
  default:
    executeUnknown();
}空のcaseは次のcaseにフォールスルーし、caseが本体を共有できるようにします。フォールスルーしない空のcaseについては、本体にbreakを使用してください。順次でないフォールスルーには、continue文とラベルを使用できます。
switch (command) {
  case 'OPEN':
    executeOpen();
    continue newCase; // Continues executing at the newCase label.
  case 'DENIED': // Empty case falls through.
  case 'CLOSED':
    executeClosed(); // Runs for both DENIED and CLOSED,
  newCase:
  case 'PENDING':
    executeNowClosed(); // Runs for both OPEN and PENDING.
}ケースが本体またはガードを共有できるようにするには、論理ORパターンを使用できます。パターンとcase節の詳細については、Switch文と式のパターンに関するドキュメントを参照してください。
switch式
#switch式は、マッチしたcaseの式本体に基づいて値を生成します。switch式は、Dartで式が許可される場所ならどこでも使用できますが、式文の先頭は除きます。例:
var x = switch (y) { ... };
print(switch (x) { ... });
return switch (x) { ... };式文の先頭でswitchを使用したい場合は、switch文を使用してください。
Switch式を使用すると、次のようなswitch文を書き換えることができます。
// Where slash, star, comma, semicolon, etc., are constant variables...
switch (charCode) {
  case slash || star || plus || minus: // Logical-or pattern
    token = operator(charCode);
  case comma || semicolon: // Logical-or pattern
    token = punctuation(charCode);
  case >= digit0 && <= digit9: // Relational and logical-and patterns
    token = number();
  default:
    throw FormatException('Invalid');
}次のような式に書き換えることができます。
token = switch (charCode) {
  slash || star || plus || minus => operator(charCode),
  comma || semicolon => punctuation(charCode),
  >= digit0 && <= digit9 => number(),
  _ => throw FormatException('Invalid'),
};switch式の構文は、switch文の構文とは異なります。
- caseはcaseキーワードで始まりません。
- caseの本体は、ステートメントのシーケンスではなく、単一の式です。
- 各caseには本体が必要です。空のcaseの暗黙的なフォールスルーはありません。
- Caseパターンは、:の代わりに=>を使用して本体から分離されます。
- Caseは,で区切られます(末尾の,はオプションで許可されます)。
- Default caseは、defaultと_の両方を許可する代わりに、_のみを使用できます。
網羅性チェック
#網羅性チェックは、値がswitchに入ってもどのcaseにも一致しない可能性がある場合に、コンパイル時エラーを報告する機能です。
// Non-exhaustive switch on bool?, missing case to match null possibility:
switch (nullableBool) {
  case true:
    print('yes');
  case false:
    print('no');
}デフォルトのcase(defaultまたは_)は、switchを通過する可能性のあるすべての値をカバーします。これにより、任意の型に対するswitchが網羅的になります。
列挙型とsealed型は、switchで特に役立ちます。なぜなら、デフォルトのcaseがなくても、それらの可能な値は既知で完全に列挙可能だからです。クラスにsealed修飾子を使用すると、そのクラスのサブタイプをswitchingするときに網羅性チェックを有効にできます。
sealed class Shape {}
class Square implements Shape {
  final double length;
  Square(this.length);
}
class Circle implements Shape {
  final double radius;
  Circle(this.radius);
}
double calculateArea(Shape shape) => switch (shape) {
  Square(length: var l) => l * l,
  Circle(radius: var r) => math.pi * r * r,
};もしShapeの新しいサブクラスが追加された場合、このswitch式は不完全になります。網羅性チェックにより、不足しているサブタイプが通知されます。これにより、Dartをある種の関数型代数的データ型スタイルで使用できます。
ガード節
#case節の後にオプションのガード節を設定するには、whenキーワードを使用します。ガード節は、if case、およびswitch文と式の両方に続くことができます。
// Switch statement:
switch (something) {
  case somePattern when some || boolean || expression:
    //             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Guard clause.
    body;
}
// Switch expression:
var value = switch (something) {
  somePattern when some || boolean || expression => body,
  //               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Guard clause.
}
// If-case statement:
if (something case somePattern when some || boolean || expression) {
  //                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Guard clause.
  body;
}ガードは、マッチング後に任意のブール式を評価します。これにより、case本体を実行するかどうかの追加の制約を追加できます。ガード節がfalseに評価されると、switch全体を終了するのではなく、次のcaseに進みます。