はじめに
Flutter でアプリを開発するには、まず Dart というプログラミング言語を理解する必要があります。
このシリーズでは、Flutter 開発に必要な Dart の文法を基礎から丁寧に解説していきます。第1回は 変数・型・演算子 です。
Dart とは?
Dart は Google が開発したプログラミング言語です。Flutter のアプリケーションはすべて Dart で記述します。
- Google が 2011 年に発表
- Flutter の公式言語
- 型安全でありながら、型推論も備える
- コンパイル言語(AOT/JIT 両対応)
DartPad で手軽に試そう
Dart のコードはブラウザ上の DartPad で即座に実行できます。環境構築は不要です。
本記事のコード例はすべて DartPad にコピー&ペーストして実行できます。
1. 変数宣言
var による宣言
var を使うと、代入した値から型が自動的に推論されます。
void main() {
var name = 'Taro'; // String と推論される
var age = 25; // int と推論される
var height = 170.5; // double と推論される
var isStudent = true; // bool と推論される
print(name); // Taro
print(age); // 25
print(height); // 170.5
print(isStudent); // true
}
var で宣言した変数は、推論された型と異なる型の値を再代入できません。
void main() {
var count = 10; // int と推論される
count = 20; // OK(同じ int 型)
// count = 'hello'; // コンパイルエラー(String は代入できない)
print(count); // 20
}
型を明示して宣言する
型を直接指定することもできます。コードの意図が明確になるため、実務では型を明示するスタイルも多く使われます。
void main() {
String name = 'Taro';
int age = 25;
double height = 170.5;
bool isStudent = true;
print('$name は $age 歳、身長 $height cm');
// Taro は 25 歳、身長 170.5 cm
}
dynamic 型
dynamic を使うと、任意の型の値を代入できます。型チェックが行われないため、ランタイムエラーの原因になりやすく、通常は使用を避けます。
void main() {
dynamic value = 'Hello';
print(value); // Hello
print(value.runtimeType); // String
value = 42;
print(value); // 42
print(value.runtimeType); // int
value = true;
print(value); // true
print(value.runtimeType); // bool
}
2. final と const
final ― 実行時に一度だけ代入
final で宣言した変数には一度だけ値を代入でき、その後は変更できません。値は 実行時 に決まります。
void main() {
final String greeting = 'Hello, Dart!';
// greeting = 'Hi!'; // コンパイルエラー(再代入不可)
print(greeting); // Hello, Dart!
// 型推論との併用も可能
final now = DateTime.now(); // 実行時の現在時刻が入る
print(now);
}
const ― コンパイル時定数
const は コンパイル時に値が確定する 定数です。実行時に決まる値(DateTime.now() など)は代入できません。
void main() {
const double pi = 3.14159265358979;
const int maxRetry = 3;
print(pi); // 3.14159265358979
print(maxRetry); // 3
// const now = DateTime.now(); // コンパイルエラー(実行時の値は不可)
}
final と const の違いまとめ
| 特徴 | final |
const |
|---|---|---|
| 再代入 | 不可 | 不可 |
| 値の決定タイミング | 実行時 | コンパイル時 |
DateTime.now() 等 |
使用可能 | 使用不可 |
| インスタンス変数 | 使用可能 | 使用不可(static const は可) |
3. 数値型: int, double, num
Dart の数値型は int(整数)と double(浮動小数点数)の2つです。num はその親クラスで、整数と小数の両方を受け取れます。
void main() {
int count = 42;
double price = 19.99;
num value = 100; // int でも double でも代入可能
print(count); // 42
print(price); // 19.99
print(value); // 100
value = 3.14; // double も代入可能
print(value); // 3.14
}
int と double の変換
void main() {
int a = 10;
double b = a.toDouble();
print(b); // 10.0
double c = 3.7;
int d = c.toInt(); // 小数部分を切り捨て
print(d); // 3
int e = c.round(); // 四捨五入
print(e); // 4
}
4. 文字列型: String
シングルクォートとダブルクォート
Dart ではどちらも使えます。Dart の公式スタイルガイド(Effective Dart)ではシングルクォートが推奨されています。
void main() {
String single = 'Hello';
String double_ = "World";
print(single); // Hello
print(double_); // World
}
文字列補間
$variable で変数を、${expression} で式を文字列中に埋め込めます。
void main() {
String name = 'Taro';
int age = 25;
// $ で変数を埋め込む
print('名前: $name'); // 名前: Taro
// ${} で式を埋め込む
print('来年は ${age + 1} 歳'); // 来年は 26 歳
// 文字列の長さ
print('名前の文字数: ${name.length}'); // 名前の文字数: 4
}
複数行文字列
トリプルクォート(''' または """)を使うと、複数行の文字列を記述できます。
void main() {
String multiLine = '''
1行目
2行目
3行目
''';
print(multiLine);
// 1行目
// 2行目
// 3行目
}
文字列の結合
+ 演算子またはリテラルの隣接で結合できます。
void main() {
String first = 'Hello';
String second = 'World';
// + で結合
print(first + ', ' + second + '!'); // Hello, World!
// リテラルの隣接(変数には使えない)
print('Hello, '
'World!'); // Hello, World!
}
5. bool 型
true または false のどちらかの値を取ります。Dart は 厳密な bool 型 を要求し、JavaScript のような暗黙の型変換は行いません。
void main() {
bool isActive = true;
bool isDeleted = false;
print(isActive); // true
print(isDeleted); // false
// if 文には bool 型のみ使用可能
// if (1) {} // コンパイルエラー(int は bool ではない)
// if ('') {} // コンパイルエラー(String は bool ではない)
if (isActive) {
print('アクティブです'); // アクティブです
}
}
6. 算術演算子
void main() {
int a = 17;
int b = 5;
print('$a + $b = ${a + b}'); // 17 + 5 = 22
print('$a - $b = ${a - b}'); // 17 - 5 = 12
print('$a * $b = ${a * b}'); // 17 * 5 = 85
print('$a / $b = ${a / b}'); // 17 / 5 = 3.4(常に double を返す)
print('$a ~/ $b = ${a ~/ b}'); // 17 ~/ 5 = 3(整数除算)
print('$a % $b = ${a % b}'); // 17 % 5 = 2(剰余)
}
| 演算子 | 意味 | 例 | 結果 |
|---|---|---|---|
+ |
加算 | 17 + 5 |
22 |
- |
減算 | 17 - 5 |
12 |
* |
乗算 | 17 * 5 |
85 |
/ |
除算(double を返す) | 17 / 5 |
3.4 |
~/ |
整数除算 | 17 ~/ 5 |
3 |
% |
剰余 | 17 % 5 |
2 |
注意: Dart の
/は常にdoubleを返します。整数の商が欲しい場合は~/を使います。これは Java や Python とは異なる Dart 独自の演算子です。
7. 比較演算子
void main() {
int x = 10;
int y = 20;
print('$x == $y → ${x == y}'); // 10 == 20 → false
print('$x != $y → ${x != y}'); // 10 != 20 → true
print('$x > $y → ${x > y}'); // 10 > 20 → false
print('$x < $y → ${x < y}'); // 10 < 20 → true
print('$x >= 10 → ${x >= 10}'); // 10 >= 10 → true
print('$x <= $y → ${x <= y}'); // 10 <= 20 → true
}
8. 論理演算子
void main() {
bool a = true;
bool b = false;
print('$a && $b → ${a && b}'); // true && false → false
print('$a || $b → ${a || b}'); // true || false → true
print('!$a → ${!a}'); // !true → false
print('!$b → ${!b}'); // !false → true
// 実用例
int age = 25;
bool hasLicense = true;
if (age >= 18 && hasLicense) {
print('運転できます'); // 運転できます
}
}
| 演算子 | 意味 | 説明 |
|---|---|---|
&& |
論理AND | 両方 true のとき true
|
|| |
論理OR | どちらか一方が true のとき true
|
! |
論理NOT |
true と false を反転 |
9. 代入演算子
void main() {
int score = 100;
print('初期値: $score'); // 初期値: 100
score += 20;
print('+= 20 → $score'); // += 20 → 120
score -= 30;
print('-= 30 → $score'); // -= 30 → 90
score *= 2;
print('*= 2 → $score'); // *= 2 → 180
score ~/= 3; // Dart の整数除算代入は ~/=
print('~/= 3 → $score'); // ~/= 3 → 60
score %= 7;
print('%= 7 → $score'); // %= 7 → 4
}
??= 演算子(null の場合のみ代入)
??= は、変数が null のときだけ値を代入します。
void main() {
String? name; // null で初期化される
print(name); // null
name ??= 'デフォルト名';
print(name); // デフォルト名
name ??= '別の名前'; // すでに null ではないので代入されない
print(name); // デフォルト名
}
10. 型チェック: is / is!
is で型チェック、is! で「その型ではない」ことを確認できます。
void main() {
dynamic value = 42;
print(value is int); // true
print(value is double); // false(※ DartPad では true。後述の注意を参照)
print(value is! String); // true
value = 'Hello';
print(value is String); // true
print(value is int); // false
}
注意: DartPad は JavaScript にコンパイルして実行するため、JavaScript の仕様上
42 is doubleがtrueになります。ネイティブ環境(dart runなど)ではfalseです。整数リテラルはint型ですが、Web 環境では内部的に全て浮動小数点数として扱われるためです。
is による型チェックの後、Dart は自動的に型を絞り込みます(スマートキャスト)。
void main() {
Object obj = 'Hello, Dart!';
if (obj is String) {
// このブロック内では obj は String として扱える
print(obj.toUpperCase()); // HELLO, DART!
print(obj.length); // 12
}
}
11. 総合的なコード例
ここまでの内容を使った実践的な例を示します。
void main() {
// 商品情報
const String productName = 'Dart入門書';
const int basePrice = 2800;
const double taxRate = 0.10;
// 税込価格を計算
final int tax = (basePrice * taxRate).toInt();
final int totalPrice = basePrice + tax;
// 結果を表示
print('=== 商品情報 ===');
print('商品名: $productName');
print('税抜価格: $basePrice 円');
print('消費税(${(taxRate * 100).toInt()}%): $tax 円');
print('税込価格: $totalPrice 円');
// === 商品情報 ===
// 商品名: Dart入門書
// 税抜価格: 2800 円
// 消費税(10%): 280 円
// 税込価格: 3080 円
// 型の確認
print('\n=== 型の確認 ===');
print('productName is String: ${productName is String}'); // true
print('basePrice is int: ${basePrice is int}'); // true
print('taxRate is double: ${taxRate is double}'); // true
}
練習問題
練習問題 1: 自己紹介プログラム
以下の変数を宣言し、文字列補間を使って自己紹介文を出力してください。
- 名前(String):
"山田花子" - 年齢(int):
28 - 趣味(String):
"読書" - プログラミング歴(double):
1.5(年)
期待する出力:
こんにちは、山田花子です!
年齢は28歳で、趣味は読書です。
プログラミング歴は1.5年です。来年は2.5年になります。
模範解答
void main() {
String name = '山田花子';
int age = 28;
String hobby = '読書';
double programmingYears = 1.5;
print('こんにちは、${name}です!');
print('年齢は${age}歳で、趣味は${hobby}です。');
print('プログラミング歴は${programmingYears}年です。来年は${programmingYears + 1}年になります。');
}
ポイント: $variable は単純な変数の埋め込みに、${expression} は式の埋め込みに使います。programmingYears + 1 は式なので ${} を使います。
練習問題 2: 円の面積と円周の計算
半径 7 の円の面積と円周を計算してください。円周率は const で 3.14159265358979 と定義してください。
- 面積 = 円周率 x 半径 x 半径
- 円周 = 2 x 円周率 x 半径
期待する出力:
半径: 7
面積: 153.93804002589985
円周: 43.982297150257104
模範解答
void main() {
const double pi = 3.14159265358979;
int radius = 7;
double area = pi * radius * radius;
double circumference = 2 * pi * radius;
print('半径: $radius');
print('面積: $area');
print('円周: $circumference');
}
ポイント:
-
pi * radius * radiusの計算では、intとdoubleの乗算結果は自動的にdoubleになります。 - 面積:
3.14159265358979 * 7 * 7 = 3.14159265358979 * 49 = 153.93804002589985 - 円周:
2 * 3.14159265358979 * 7 = 43.982297150257104
練習問題 3: 型の判定プログラム
dynamic 型の変数に順番に異なる型の値を代入し、is 演算子で型を判定して結果を出力してください。
以下の値を順番に判定してください: 42, 3.14, 'Dart', true
期待する出力:
値: 42 → int: true, double: false, String: false, bool: false ※ DartPad では double: true
値: 3.14 → int: false, double: true, String: false, bool: false
値: Dart → int: false, double: false, String: true, bool: false
値: true → int: false, double: false, String: false, bool: true
模範解答
void main() {
dynamic value;
value = 42;
print('値: $value → int: ${value is int}, double: ${value is double}, String: ${value is String}, bool: ${value is bool}');
value = 3.14;
print('値: $value → int: ${value is int}, double: ${value is double}, String: ${value is String}, bool: ${value is bool}');
value = 'Dart';
print('値: $value → int: ${value is int}, double: ${value is double}, String: ${value is String}, bool: ${value is bool}');
value = true;
print('値: $value → int: ${value is int}, double: ${value is double}, String: ${value is String}, bool: ${value is bool}');
}
ポイント: is 演算子はランタイムの型を判定します。dynamic 型の変数でも、実際に格納されている値の型に基づいて正確に判定されます。
まとめ
| 項目 | 内容 |
|---|---|
| 変数宣言 |
var(型推論)、型を明示、dynamic(非推奨) |
| 再代入不可 |
final(実行時)、const(コンパイル時) |
| 数値型 |
int、double、num(親クラス) |
| 文字列 | シングル/ダブルクォート、$/${}補間、'''複数行 |
| bool |
true/false(暗黙変換なし) |
| 算術演算子 |
+, -, *, /(double), ~/(整数除算), %
|
| 比較演算子 |
==, !=, >, <, >=, <=
|
| 論理演算子 |
&&, ||, !
|
| 代入演算子 |
=, +=, -=, *=, /=, ??=
|
| 型チェック |
is, is!(スマートキャスト付き) |
次回(第2回)は 制御構文(if / for / while / switch) を学びます。
参考
- Dart Language Tour - Variables
- Dart Language Tour - Built-in types
- Dart Language Tour - Operators
- Effective Dart: Style
- DartPad
@kotaro_ai_lab
AI活用や開発効率化について発信しています。フォローお気軽にどうぞ!