【入門編】DartのNull-aware演算子(??, ?., ??=)を駆使した簡潔なコード記述術 – Dart コア文法・オブジェクト指向・Null安全解析バイブル

こんにちは!FlutterやDartを使った開発を楽しんでいますか?
他のプログラミング言語からDartの世界に飛び込んできたとき、多くの開発者が最初に感動するのが、この「Sound Null Safety(健全なNull安全)」と、それに伴うエレガントな演算子たちです。

「変数に `null` が入るかもしれない」という恐怖から私たちを解放しつつ、冗長な `if (foo != null)` のようなボイラープレートコードを消し去ってくれるのが、DartのNull-aware(Null認識型)演算子たちです。

今回は、基本の「キ」から、現場で即戦力になるスマートな書き方まで、優しく、そして深く紐解いていきましょう。ここをクリアすれば、あなたのDartコードは見違えるほど洗練されますよ!

—

1. なぜDartのNull安全は強力なのか?(おさらい)

JavaやJavaScriptなどの言語で、突然の `TypeError: Cannot read property ‘foo’ of null`(いわゆる「NullP」や「ナリポ」)に頭を抱えた経験はありませんか?

DartのNull安全は、「デフォルトでは、すべての変数は `null` 非許容(絶対にnullにならない)」という鉄則から始まります。

String name = ‘Dart’; // 絶対にnullは入りません
// name = null; // ← これはコンパイルエラーになります!

もし `null` を許容したい場合は、型名の後ろに `?` を明示的に付けます。

String? nullableName = ‘Dart’; // nullが入ってもOK
nullableName = null; // コンパイル通ります

この「型システムレベルで `null` を完全にコントロールできる世界」において、コードをスマートに保つための最強の三銃士が `??`, `?.`, `??=` です。さっそく見ていきましょう!

—

2. 三大Null-aware演算子をマスターする

① 安全なプロパティ・メソッド呼び出し:`?.` (Null-aware Member Access)

「もしこの変数が `null` じゃなかったらプロパティにアクセスして、もし `null` ならエラーを出さずに全体を `null` にしてね」という、優しさの塊のような演算子です。

【従来の冗長なコード】

String? getUpperName(String? name) {
if (name != null) {
return name.toUpperCase();
}
return null;
}

【`?.` を使ったDartらしいコード】

String? getUpperName(String? name) {
return name?.toUpperCase(); // nameがnullなら、ここで評価がストップしてnullを返す
}

これだけでも十分スッキリしますが、さらにリストやメソッドチェーンと組み合わせると真価を発揮します。
「もしリスト自体が `null` だった場合」も、`?.` があれば安全にスルーしてくれます。

—

② デフォルト値のフォールバック:`??` (If-null Operator)

「左側の値が `null` だったら、右側の値を採用する」という、いわゆるフォールバック(代替え)を行う演算子です。JavaScriptの `??`(Null合体演算子)やC#のそれと同じ挙動をします。

【具体的な使い方】

void printUsername(String? username) {
// usernameがnullなら ‘ゲスト’ を表示する
String displayName = username ?? ‘ゲスト’;
print(‘ようこそ、$displayName さん!’);
}

void main() {
printUsername(‘Alice’); // 出力: ようこそ、Alice さん!
printUsername(null); // 出力: ようこそ、ゲスト さん!
}

三項演算子(`condition ? a : b`)を使って長々と書く必要はもうありません。`??` を使えば、意図がひと目で伝わる美しいコードになります。

—

③ 変数が未初期化のときだけ代入する:`??=` (Null-aware Assignment)

最後は少し通好みな、でも現場でめちゃくちゃ重宝する代入演算子です。
「その変数にまだ値が入っていない(つまり `null` である)時だけ、右側の値を代入する」という動作をします。

【具体的な使い方】

class Config {
String? _theme;

// テーマが設定されていなければデフォルトを設定する
void setTheme(String? newTheme) {
_theme ??= ‘dark’; // _themeがnullの時だけ ‘dark’ が代入される
}
}

何回メソッドが呼ばれても、最初に `null` だった瞬間の一回だけ代入が行われ、すでに値が入っている場合はスルーされます。キャッシュの初期化や遅延初期化(Lazy Initialization)の文脈で非常に強力です。

—

3. 実践!これらを組み合わせて「極限まで簡潔なコード」を書く

では、これまで学んだ演算子たちを組み合わせて、実際のアプリケーション開発でよくあるシチュエーションを書いてみましょう。

シチュエーション:ユーザーのプロフィール表示ロジック

class UserProfile {
final String? nickname;
final int? age;

UserProfile({this.nickname, this.age});

String getDisplayInfo() {
// 1. nicknameがnullなら ‘名無しの権兵衛’ にしつつ、大文字変換する
// 2. ageがnullなら ‘未設定’ と表示する

final name = nickname?.toUpperCase() ?? ‘名無しの権兵衛’;
final ageStr = age?.toString() ?? ‘未設定’;

return ‘名前: $name / 年齢: $ageStr歳’;
}
}

void main() {
// パターンA: データがしっかりある場合
var user1 = UserProfile(nickname: ‘dartist’, age: 28);
print(user1.getDisplayInfo());
// 出力: 名前: DARTIST / 年齢: 28歳

// パターンB: データがごっそり null の場合
var user2 = UserProfile();
print(user2.getDisplayInfo());
// 出力: 名前: 名無しの権兵衛 / 年齢: 未設定歳
}

どうでしょう? `if` 文や三項演算子を一切使っていないのに、意図が完璧にクリアで、しかも絶対に実行時エラー(NullP)が起きない安全性が保証されています。これがDartの真骨頂です。

—

4. 陥りがちな文法エラーと注意点

初心者のうちは、これらの演算子を使う際にいくつか「やりがちなミス」があります。ここで先回りして押さえておきましょう。

① `?.` の連鎖による「意図しない型変化」に注意

`?.` をチェーンさせると、途中のどこかで `null` が返った瞬間、全体の型が `null` 許容型(`?`付き)になります。

String? countryCode = user?.address?.country?.code;
// user, address, country のいずれかがnullの可能性があるため、
// countryCode の型は自動的に String? になります。

「絶対に `null` にならないはず!」と思い込んで `String` 型の変数に直接代入しようとすると、コンパイラに「それ `null` かもしれないよ?」と怒られます(Type Mismatch)。型推論に頼りすぎず、左辺の型がどう評価されるかを意識しましょう。

② `??` と三項演算子の優先順位

複数の演算子を1行に詰め込みすぎると、意図しない順番で評価されることがあります。迷ったらカッコ `()` を使って評価の優先順位を明確にしましょう。

// 良くない例(読みづらくバグの温床になりやすい)
var result = a ?? b ? c : d;

// 良い例(カッコで意図を明示する)
var result = (a ?? b) ? c : d;

—

まとめ

今回はDartのNull-aware演算子(`??`, `?.`, `??=`)について解説しました。

  • `?.` : 安全にプロパティやメソッドを覗き見する
  • `??` : `null` だった場合のセーフティネット(デフォルト値)を用意する
  • `??=` : `null` のときだけお代わり(代入)を注ぐ

これらを使いこなせるようになると、コードから無駄な `if` 文がごっそり消え、ビジネスロジックの本質だけに集中できるようになります。

Dartの厳格なNull安全は、最初は少し厳しく感じるかもしれませんが、あなたのコードを守る最強の相棒です。ぜひ明日のコーディングから、これらの演算子をガンガン活用してみてくださいね!

それでは、快適なDartライフを!

タイトルとURLをコピーしました