こんにちは!FlutterやDartのコードを日々書いていく中で、「もっとスマートに条件分岐やバリデーションを書きたいな」と感じたことはありませんか?
他の言語、例えばTypeScriptやRustなどでパターンマッチングの便利さを知っている方なら、「Dart 3のパターンマッチングはどう使うんだろう?」とワクワクしているかもしれませんね。
今回は、Dart 3で導入された強力な武器である「論理演算パターン(AND / OR パターン)」にフォーカスして、複雑なデータ構造のバリデーションを美しく、そして一撃でクリアにするテクニックを伝授します。
ここをクリアすれば、あなたのDartコードは一段と洗練されますよ。一緒にマスターしていきましょう!
—
1. Dart 3のパターンマッチングとは?(ざっくりおさらい)
これまでのDartでは、複雑なオブジェクトのデータをチェックするときに、何度も`if`文やプロパティのアクセスを繰り返す必要がありましたよね。
// 昔ながらの書き方(少し冗長ですよね)
if (user != null) {
if (user.age >= 18) {
if (user.status == ‘active’ || user.status == ‘pending’) {
// 処理…
}
}
}
Dart 3で導入されたパターンマッチングを使えば、この「データの形そのもの」を表現して、変数にマッチするかどうかを判定できるようになりました。その中でも、複数の条件を組み合わせる論理演算パターン(`&&` と `||`)は、実務のバリデーションで爆発的な威力を発揮します。
—
2. 論理演算パターンの基本:OR (`||`) と AND (`&&`)
まずは、論理演算パターンの基本的な姿を見てみましょう。パターンマッチングの中では、論理演算子は次のような意味を持ちます。
- OR パターン (`pattern1 || pattern2`): どちらか一方のパターンにマッチすればOK。
- AND パターン (`pattern1 && pattern2`): 両方のパターンに同時にマッチする必要がある。
イメージ図:データのチェックフロー
[入力データ] ──> ( パターン A || パターン B ) ──> どちらか一致すればOK!
[入力データ] ──> ( 条件 X && 条件 Y ) ──> 両方満たせばOK!
では、具体的なコードでその動きを確認してみましょう。
—
3. 実践!複雑なバリデーションを一行で書く
例えば、ECサイトのユーザー情報を想像してください。
「VIP会員、または年齢が20歳以上かつアクティブなユーザー」という、少し入り組んだ条件をバリデーションしたいとします。
これをDart 3の `switch` 式と論理演算パターンを使って書くと、こうなります。
// ユーザーを表すレコード(あるいはクラス)
class User {
final String name;
final int age;
final String membership; // ‘vip’, ‘regular’, ‘guest’
final bool isActive;
User(this.name, this.age, this.membership, this.isActive);
}
void validateUser(User user) {
// switch式とパターンマッチングの組み合わせ
String accessLevel = switch (user) {
// 【ORパターンの活用】 VIP会員、または (20歳以上かつアクティブ) の場合
(var u) when u.membership == ‘vip’ || (u.age >= 20 && u.isActive)
=> ‘フルアクセス許可’,
// それ以外
_ => ‘アクセス制限中’,
};
print(‘${user.name}さん: $accessLevel’);
}
void main() {
// テストデータの作成
var alice = User(‘Alice’, 17, ‘vip’, false); ; // VIPなのでOK
var bob = User(‘Bob’, 22, ‘regular’, true); ; // 20歳以上かつアクティブなのでOK
var charlie = User(‘Charlie’, 19, ‘regular’, true); // 条件を満たさないのでNG
validateUser(alice); // 出力: Aliceさん:フルアクセス許可
validateUser(bob); // 出力: Bobさん:フルアクセス許可
validateUser(charlie); // 出力: Charlieさん:アクセス制限中
}
ここで注目してほしいのは、条件判定の部分です。
`||`(OR)と `&&`(AND)を組み合わせることで、本来ならネスト(入れ子)になりがちな複雑なビジネスロジックを、直感的な一行の式として表現できていますよね。
—
4. さらにスマートに!オブジェクトパターンとの組み合わせ
Dart 3の真骨頂は、オブジェクトのプロパティを直接分解(Destructuring)しながら、論理演算を適用できる点にあります。先ほどのコードを、もっとDartらしく洗練させてみましょう。
void smartValidate(User user) {
// オブジェクトのプロパティを直接パターンマッチングにかける
final message = switch (user) {
// membershipが ‘vip’、あるいは (ageが20以上 かつ isActiveがtrue)
(User(membership: ‘vip’) || User(age: >= 20, isActive: true))
=> ‘特権ルートを通ります’,
_ => ‘一般ルートを通ります’,
};
print(message);
}
どうですか?わざわざ一時変数 `u` を経由しなくても、データの構造(`User(age: >= 20, …)`)そのものに条件(関係演算子 `>=`)を組み込み、それを `||` で繋ぐことができています。これが、Dart 3が提供するモダンでエレガントな世界観です。
—
5. 初学者が陥りやすい文法エラーと注意点
新しい機能を学ぶとき、誰もが一度はハマるポイントがあります。ここで先回りして注意点を確認しておきましょう。
注意点1: 変数のバインド(束縛)スコープに気をつける
ORパターン (`||`) の左右で、異なる変数名に値をバインドしようとすると、コンパイルエラーになります。ORの性質上、「どちらのルートを通るかによって作られる変数が変わる可能性がある」ためです。
// ❌ やってはいけない例
// 左右で異なる変数をキャプチャしようとするとDart VMが混乱します
switch (number) {
case int x || String x: // OKな場合もありますが、複雑な構造では制限があります
print(x);
break;
}
解決策: ORパターンの左右では、同じ構造や同じ型の変数を扱うか、純粋に値の比較(定数パターンや関係演算子)に留めるのが安全です。
注意点2: 網羅性チェック(Exhaustiveness Checking)を忘れない
Dart 3の `switch` 式は非常に優秀で、「すべてのケースを網羅しているか」をコンパイル時にチェックしてくれます。もし論理演算パターンを使っていて、意図せず「どのパターンにも当てはまらない隙間」ができてしまうと、コンパイラに怒られてしまいます。
必ず最後に `_ => …` (デフォルトケース)を用意して、安全ネットを張る癖をつけておきましょう。
—
まとめ:ここをクリアすればDartの基本はバッチリ!
今回は、Dart 3のパターンマッチングにおける「論理演算パターン」の活用術をご紹介しました。
- ORパターン (`||`) で「これ、またはあれ」という柔軟な条件分岐ができる。
- ANDパターン (`&&`) と組み合わせることで、複雑なバリデーションをフラットに記述できる。
- オブジェクトの構造分解と組み合わせることで、コードの量が劇的に減り、可読性が跳ね上がる。
最初は見慣れない構文に戸惑うかもしれませんが、一度この書き方に慣れると、もう以前の冗長な `if-else` の世界には戻れなくなりますよ。
ぜひ今日のコードを手元の開発環境で動かして、そのスッキリ感を体感してみてくださいね。
あなたのDartマスターへの道を、これからも応援しています!