Dart 演算子
演算子は、プログラム内で計算・比較・論理判定を実行する記号です。
この章では、Dart のさまざまな演算子について体系的に説明します。算術、関係、論理、代入、条件演算子、型検査などを含みます。
算術演算子
算術演算子は基本的な数学演算を実行するために使用されます。
実例
int a = 10;
int b = 3;
print('a = $a, b = $b');
print('加算 a + b = ${a + b}'); // 13
print('減算 a - b = ${a - b}'); // 7
print('乗算 a * b = ${a * b}'); // 30
print('除算 a / b = ${a / b}'); // 3.333... (結果は double)
print('整数除算 a ~/ b = ${a ~/ b}'); // 3 (整数化、小数切り捨て)
print('剰余 a % b = ${a % b}'); // 1 (剰余演算)
print('符号反転 -a = ${-a}'); // -10 (単項マイナス)
}
a = 10, b = 3 加法 a + b = 13 减法 a - b = 7 乘法 a * b = 30 除法 a / b = 3.3333333333333335 整除 a ~/ b = 3 取余 a % b = 1 取反 -a = -10
注意:/ 演算子は、2つのオペランドがともに int で割り切れる場合でも、常に double 型を返します。整数の結果だけが必要な場合は、~/ 整除演算子を使用してください。
インクリメント/デクリメント演算子
多くのC言語系言語と同様に、Dart は ++(インクリメント)と --(デクリメント)をサポートしています。
実例
int count = 0;
// 前置 ++:先にインクリメントしてから使用
print('前置 ++: ${++count}'); // 1
// 後置 ++:使用してからインクリメント
print('後置 ++: ${count++}'); // 1(この時点では count はまだ 1)
print('現在 count = $count'); // 2
// デクリメントも同様
print('前置 --: ${--count}'); // 1
print('後置 --: ${count--}'); // 1
print('現在 count = $count'); // 0
}
前置 ++: 1 后置 ++: 1 现在 count = 2 前置 --: 1 后置 --: 1 现在 count = 0
前置と後置のインクリメント/デクリメントは、単独で使用した場合は同じ効果ですが、式の中で使用すると動作が異なります。初心者は式の中で使うのは避けて、単独の行に書くほうが分かりやすいでしょう。
関係演算子
関係演算子は、2つの値を比較するために使用され、結果は bool 値です。
| 演算子 | 意味 | 例 | 結果 |
|---|---|---|---|
| == | 等しい | 5 == 5 | true |
| != | 等しくない | 5 != 3 | true |
| > | より大きい | 5 > 3 | true |
| < | より小さい | 5 < 3 | false |
| >= | 以上 | 5 >= 5 | true |
| <= | 以下 | 3 <= 5 | true |
実例
int サンプルScore = 95;
int passLine = 60;
print('点数: $サンプルScore, 合格ライン: $passLine');
print('合格しましたか? ${サンプルScore >= passLine}');
print('満点でしたか? ${サンプルScore == 100}');
// 文字列も比較できます
String a = 'apple';
String b = 'banana';
print("'$a' == '$b'? ${a == b}");
// == は値が等しいかどうかを判定します
String c = 'サンプル';
String d = 'サンプル';
print("'$c' == '$d'? ${c == d}"); // true(内容が同じ)
}
分数: 95, 及格线: 60 及格了吗? true 满分了吗? false 'apple' == 'banana'? false 'サンプル' == 'サンプル'? true
Dart の == は、2つのオブジェクトの値が等しいかどうかを比較し、参照アドレスは比較しません。これは Java とは異なります。Dart では文字列を比較するのに equals() メソッドを使う必要はありません。
論理演算子
論理演算子は、複数の bool 式を組み合わせるために使用され、通常は条件判定に使われます。
| 演算子 | 意味 | 説明 |
|---|---|---|
| && | 論理積 | 両方とも true の場合のみ true を返します |
| || | 論理和 | どちらか一方が true なら true を返します |
| ! | 論理否定 | 反転します。true は false に、false は true になります。 |
実例
bool isLoggedIn = true;
bool isAdmin = false;
// && 論理積:両方とも true
print('ログイン済みかつ管理者: ${isLoggedIn && isAdmin}'); // false
// || 論理和:少なくとも1つが true
print('ログイン済みまたは管理者: ${isLoggedIn || isAdmin}'); // true
// ! 論理否定:反転
print('未ログイン: ${!isLoggedIn}'); // false
// 短絡評価:左辺で結果が確定している場合、右辺は実行されない
int age = 20;
// age > 18 は true だが、右辺も確認する必要がある
print('成人かつ権限あり: ${age >= 18 && isAdmin}');
// age < 18 が false なので、&& の右辺はスキップされる
print('未成年かつ権限あり: ${age < 18 && isAdmin}');
}
登录且是管理员: false 登录或是管理员: true 未登录: false 成年且有权限: false 未成年且有权限: false
Dart では短絡評価(Short-circuit Evaluation):&& の場合、左辺が false なら右辺は計算されません。|| の場合、左辺が true なら右辺は計算されません。
この特性は、null ポインタの問題を回避するために使用できます。
実例
短絡評価の実際の応用:
String? username;
// 安全な判定:username が null でなく、かつ長さが 3 より大きい
// username が null の場合、&& の右辺は実行されないため、null ポインタエラーを回避できる
if (username != null && username.length > 3) {
print('有効なユーザー名');
} else {
print('ユーザー名が無効、または短すぎます');
}
}
ユーザー名が無効または短すぎます
代入演算子
基本的な代入演算子 = はすでにご存知でしょう。
Dart には複合代入演算子もあり、一般的な「計算してから代入する」操作を簡素化します。
| 演算子 | 等価な書き方 | 例(a=10 の場合) |
|---|---|---|
| += | a = a + b | a += 3 → 13 |
| -= | a = a - b | a -= 3 → 7 |
| *= | a = a * b | a *= 3 → 30 |
| /= | a = a / b | a /= 2 → 5.0 |
| ~/= | a = a ~/ b | a ~/= 3 → 3 |
| %= | a = a % b | a %= 3 → 1 |
実例
int score = 0;
// 正解するたびに 10 点加算
score += 10;
print('第1問正解: $score');
score += 10;
print('第2問正解: $score');
// 不正解の場合は 5 点減点
score -= 5;
print('1問不正解: $score');
// スコアが2倍になる
score *= 2;
print('ボーナス2倍: $score');
print('サンプル 最終スコア: $score');
}
答对第1题: 10 答对第2题: 20 答错1题: 15 奖励翻倍: 30 サンプル 最终得分: 30
条件演算子:?? と ??=
これらの2つの演算子は null 値を処理するために設計されており、Dart の null 安全性システムの重要な構成要素です。
?? null合体演算子
左辺の式が null でない場合は左辺の値を返し、それ以外の場合は右辺の値を返します。
??= null代入演算子
変数が現在 null の場合、右辺の値を代入します。それ以外の場合は変更されません。
実例
// ?? null合体
String? nickname;
String displayName = nickname ?? 'サンプル ユーザー';
print(displayName); // サンプル ユーザー
nickname = '小R';
displayName = nickname ?? 'サンプル ユーザー';
print(displayName); // 小R
// チェーン ?? も可能です
String? a;
String? b;
String result = a ?? b ?? 'デフォルト値';
print(result); // デフォルト値
// ??= null代入
int? count;
count ??= 0; // count が null なので 0 を代入
print(count); // 0
count ??= 100; // count はすでに 0(null ではない)ので代入しない
print(count); // 0(変更なし)
}
サンプル 用户 小R 默认值 0 0
三項条件演算子 ? :
これは Dart で唯一の3つのオペランドを持つ演算子で、if-else の簡潔なバージョンです。
実例
int score = 75;
// 構文:条件 ? trueの場合の値 : falseの場合の値
String result = score >= 60 ? '合格' : '不合格';
print('サンプル 試験結果: $result');
// ネストして使用できます(ただし、2段階を超えるのは推奨されません。可読性が低下します)
String grade = score >= 90 ? '優秀' : score >= 60 ? '合格' : 不合格;
print(評価: $grade);
}
サンプル 考试结果: 及格 评级: 及格
型検査演算子:is と as
is はオブジェクトがある型に属するかどうかをチェックするために使い、as は型変換に使います。
実例
// is:型チェック
var name = 'サンプル';
print('name は String ですか? ${name is String}'); // true
print('name は int ですか? ${name is int}'); // false
// is!:ある型ではない
print('name は int ではないですか? ${name is! int}'); // true
// as:型変換
Object obj = 'Hello, Dart!';
// Object 型を String に変換して、String のメソッドを使えるようにする
String str = obj as String;
print(str.toUpperCase());
// 安全な型判定 + 変換
Object maybeString = 42;
if (maybeString is String) {
// is 判定が true の分岐では、変数は自動的にその型に"昇格"します
print(maybeString.length); // as による変換は不要
} else {
print('文字列ではない、値: $maybeString');
}
}
name 是 String 吗? true name 是 int 吗? false name 不是 int 吗? true HELLO, DART! 不是字符串,值是: 42
is による型判定を優先します。is が true となる条件分岐内では、Dart は自動的に変数を目的の型に昇格させます(Type Promotion)。as による強制変換は不要です。as は「型が確実だがコンパイラーが推論できない」場合にのみ使います。
演算子の優先順位一覧
式に複数の演算子がある場合、Dart は優先順位の高い順に計算します。
優先順位が不明な場合、最も確実な方法は括弧を使って計算順序を明確にすることです。
| 優先順位 | 演算子 | 説明 |
|---|---|---|
| 最高 | () [] . ?. | 括弧、添字、メンバーアクセス |
| ! ~ - ++ -- | 単項演算子 | |
| * / % ~/ | 乗除、剰余 | |
| + - | 加減 | |
| < <= > >= | 関係比較 | |
| == != | 等価判定 | |
| && | 論理積 | |
| || | 論理和 | |
| ?? | Null 合体 | |
| ? : | 三項条件 | |
| = += -= *= など | 代入(結合順位が最も低い) |
実例
// 優先順位に頼らず、括弧で意図を明確にする
int result = ((10 + 5) * 2) - (8 ~/ 3);
print('計算結果: $result'); // 28
// 括弧を付けないと、結果がまったく異なる可能性がある
// 10 + 5 * 2 - 8 ~/ 3 の結果は 18 になります(乗除を先に、加減を後に)
int result2 = 10 + 5 * 2 - 8 ~/ 3;
print('括弧なし: $result2'); // 18
}
计算结果: 28 不加括号: 18その他の拡張