第2章 基本文法

変数と定数(var, final, const)

Dartでは、データを格納するために変数と定数を使用します。

var – 型推論による変数宣言

void main() {
  var name = '太郎';  // Stringと推論される
  var age = 25;       // intと推論される
  var height = 175.5; // doubleと推論される
  
  print('$name ($age歳) 身長: $height cm');
  
  // 値の変更が可能
  age = 26;
  print('誕生日を迎えました。年齢: $age');
}

明示的な型宣言

void main() {
  String name = '花子';
  int score = 95;
  double temperature = 36.5;
  bool isStudent = true;
  
  print('名前: $name, 点数: $score, 体温: $temperature℃');
}

final – 実行時に一度だけ設定される定数

void main() {
  final currentTime = DateTime.now(); // 実行時に決定
  final pi = 3.14159;
  
  print('現在時刻: $currentTime');
  
  // エラー:finalは再代入できない
  // currentTime = DateTime.now();
}

const – コンパイル時定数

void main() {
  const pi = 3.14159;           // コンパイル時に決定
  const appName = 'MyApp';
  const maxUsers = 100;
  
  print('円周率: $pi');
  
  // エラー:constは再代入できない
  // pi = 3.14;
  
  // エラー:constはコンパイル時に値が確定している必要がある
  // const now = DateTime.now();
}

var、final、constの使い分け

キーワード再代入決定時期使用場面
var可能実行時値が変更される変数
final不可実行時一度設定したら変更しない値
const不可コンパイル時完全に固定された定数

データ型(int, double, String, bool)

int – 整数型

void main() {
  int age = 25;
  int negative = -10;
  int hex = 0xFF;  // 16進数: 255
  
  print('年齢: $age');
  print('16進数0xFFは10進数で: $hex');
  
  // 演算
  int sum = 10 + 20;
  int product = 5 * 6;
  int quotient = 10 ~/ 3;  // 整数除算: 3
  int remainder = 10 % 3;   // 剰余: 1
  
  print('商: $quotient, 余り: $remainder');
}

double – 浮動小数点数型

void main() {
  double pi = 3.14159;
  double temperature = 36.5;
  double scientific = 1.5e3;  // 1.5 × 10^3 = 1500.0
  
  print('円周率: $pi');
  print('科学的記法: $scientific');
  
  // 演算
  double result = 10.0 / 3.0;  // 3.3333...
  print('10 ÷ 3 = $result');
  
  // 精度指定
  print('小数点以下2桁: ${result.toStringAsFixed(2)}');
}

num – intとdoubleの共通親型

void main() {
  num value1 = 10;      // intを代入可能
  num value2 = 3.14;    // doubleを代入可能
  
  print('value1: $value1 (${value1.runtimeType})');
  print('value2: $value2 (${value2.runtimeType})');
}

String – 文字列型

void main() {
  String name = '山田太郎';
  String greeting = "こんにちは";  // シングル・ダブル両方可
  
  // 文字列補間
  String message = '$greetingさん、$nameです';
  print(message);
  
  // 式の埋め込み
  int age = 25;
  print('来年は${age + 1}歳になります');
  
  // 複数行文字列
  String multiline = '''
  これは
  複数行の
  文字列です
  ''';
  print(multiline);
  
  // 文字列の連結
  String fullName = '山田' + '太郎';
  String fullName2 = '山田' '太郎';  // 隣接する文字列は自動連結
  
  // 文字列のメソッド
  print('長さ: ${name.length}');
  print('大文字: ${'hello'.toUpperCase()}');
  print('含まれる: ${'hello world'.contains('world')}');
  print('分割: ${'apple,banana,orange'.split(',')}');
}

bool – 真偽値型

void main() {
  bool isStudent = true;
  bool hasLicense = false;
  
  print('学生ですか?: $isStudent');
  
  // 比較演算の結果もbool
  bool isAdult = 20 >= 18;
  print('成人ですか?: $isAdult');
  
  // 論理演算
  bool canDrive = isAdult && hasLicense;
  print('運転できますか?: $canDrive');
}

型変換

void main() {
  // String → int/double
  String numStr = '123';
  int num1 = int.parse(numStr);
  double num2 = double.parse('3.14');
  
  print('変換結果: $num1, $num2');
  
  // int/double → String
  int age = 25;
  String ageStr = age.toString();
  String ageStr2 = '$age';  // より簡潔
  
  print('文字列化: $ageStr');
  
  // int ⇔ double
  int intValue = 10;
  double doubleValue = intValue.toDouble();
  
  double pi = 3.14;
  int truncated = pi.toInt();  // 3(切り捨て)
  int rounded = pi.round();    // 3(四捨五入)
  
  print('切り捨て: $truncated, 四捨五入: $rounded');
}

演算子

算術演算子

void main() {
  int a = 10, b = 3;
  
  print('加算: ${a + b}');      // 13
  print('減算: ${a - b}');      // 7
  print('乗算: ${a * b}');      // 30
  print('除算: ${a / b}');      // 3.333... (double)
  print('整数除算: ${a ~/ b}'); // 3 (int)
  print('剰余: ${a % b}');      // 1
  
  // 単項演算子
  int c = 5;
  print('負数: ${-c}');         // -5
  
  // インクリメント・デクリメント
  int d = 10;
  print('後置: ${d++}');        // 10 (使用後に増加)
  print('結果: $d');            // 11
  
  int e = 10;
  print('前置: ${++e}');        // 11 (増加後に使用)
  print('結果: $e');            // 11
}

比較演算子

void main() {
  int x = 10, y = 20;
  
  print('等しい: ${x == y}');           // false
  print('等しくない: ${x != y}');       // true
  print('より大きい: ${x > y}');        // false
  print('より小さい: ${x < y}');        // true
  print('以上: ${x >= 10}');            // true
  print('以下: ${y <= 20}');            // true
}

論理演算子

void main() {
  bool a = true, b = false;
  
  print('AND: ${a && b}');     // false
  print('OR: ${a || b}');      // true
  print('NOT: ${!a}');         // false
  
  // 短絡評価
  int? value = null;
  bool result = value != null && value > 10;
  print('短絡評価: $result');  // false (value > 10は評価されない)
}

代入演算子

void main() {
  int a = 10;
  
  a += 5;   // a = a + 5
  print('+=: $a');  // 15
  
  a -= 3;   // a = a - 3
  print('-=: $a');  // 12
  
  a *= 2;   // a = a * 2
  print('*=: $a');  // 24
  
  a ~/= 5;  // a = a ~/ 5
  print('~/=: $a'); // 4
  
  // Null合体代入演算子
  String? name;
  name ??= '名前なし';  // nameがnullの場合のみ代入
  print('name: $name'); // 名前なし
}

条件演算子(三項演算子)

void main() {
  int age = 20;
  String status = age >= 18 ? '成人' : '未成年';
  print('ステータス: $status');
  
  // Null合体演算子
  String? username = null;
  String displayName = username ?? 'ゲスト';
  print('表示名: $displayName');  // ゲスト
}

カスケード記法

class Person {
  String? name;
  int? age;
  
  void introduce() {
    print('$nameです。$age歳です。');
  }
}

void main() {
  // 通常の方法
  var person1 = Person();
  person1.name = '太郎';
  person1.age = 25;
  person1.introduce();
  
  // カスケード記法
  var person2 = Person()
    ..name = '花子'
    ..age = 23
    ..introduce();
}

制御構文(if, switch, for, while)

if文

void main() {
  int score = 85;
  
  // 基本的なif文
  if (score >= 80) {
    print('優秀です');
  }
  
  // if-else
  if (score >= 60) {
    print('合格');
  } else {
    print('不合格');
  }
  
  // if-else if-else
  if (score >= 90) {
    print('評価: A');
  } else if (score >= 80) {
    print('評価: B');
  } else if (score >= 70) {
    print('評価: C');
  } else if (score >= 60) {
    print('評価: D');
  } else {
    print('評価: F');
  }
  
  // 条件式
  String result = score >= 60 ? '合格' : '不合格';
  print(result);
}

switch文

void main() {
  String grade = 'B';
  
  // 基本的なswitch文
  switch (grade) {
    case 'A':
      print('素晴らしい!');
      break;
    case 'B':
      print('良好です');
      break;
    case 'C':
      print('普通です');
      break;
    default:
      print('評価なし');
  }
  
  // 複数のcaseをまとめる
  int dayOfWeek = 6;
  
  switch (dayOfWeek) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
      print('平日');
      break;
    case 6:
    case 7:
      print('週末');
      break;
    default:
      print('不正な値');
  }
  
  // continueを使った処理の継続
  String command = 'start';
  
  switch (command) {
    case 'start':
      print('開始します');
      continue processing;  // processingラベルへジャンプ
    processing:
    case 'process':
      print('処理中...');
      break;
    case 'stop':
      print('停止します');
      break;
  }
}

for文

void main() {
  // 基本的なfor文
  print('=== 基本的なfor文 ===');
  for (int i = 0; i < 5; i++) {
    print('i = $i');
  }
  
  // 複数の変数
  print('\n=== 複数の変数 ===');
  for (int i = 0, j = 10; i < 5; i++, j--) {
    print('i = $i, j = $j');
  }
  
  // for-in文(コレクション用)
  print('\n=== for-in文 ===');
  List<String> fruits = ['りんご', 'バナナ', 'オレンジ'];
  for (var fruit in fruits) {
    print(fruit);
  }
  
  // forEach(関数型)
  print('\n=== forEach ===');
  fruits.forEach((fruit) {
    print('好きな果物: $fruit');
  });
  
  // break と continue
  print('\n=== break と continue ===');
  for (int i = 0; i < 10; i++) {
    if (i == 3) continue;  // 3はスキップ
    if (i == 7) break;     // 7で終了
    print(i);
  }
}

while文とdo-while文

void main() {
  // while文
  print('=== while文 ===');
  int count = 0;
  while (count < 5) {
    print('count: $count');
    count++;
  }
  
  // do-while文(最低1回は実行される)
  print('\n=== do-while文 ===');
  int num = 0;
  do {
    print('num: $num');
    num++;
  } while (num < 3);
  
  // 条件が最初から偽の場合
  print('\n=== 最初から条件が偽 ===');
  int x = 10;
  
  // while文は実行されない
  while (x < 5) {
    print('これは表示されません');
  }
  
  // do-while文は1回実行される
  do {
    print('x = $x(1回だけ実行される)');
  } while (x < 5);
}

ラベル付きループ

void main() {
  // ネストされたループからの脱出
  outer:
  for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
      print('i=$i, j=$j');
      if (i == 1 && j == 1) {
        break outer;  // 外側のループを抜ける
      }
    }
  }
  print('ループ終了');
}

関数の基礎

基本的な関数定義

// 戻り値ありの関数
int add(int a, int b) {
  return a + b;
}

// 戻り値なしの関数
void greet(String name) {
  print('こんにちは、$nameさん!');
}

// アロー関数(式が1つの場合)
int multiply(int a, int b) => a * b;

void main() {
  int result = add(5, 3);
  print('5 + 3 = $result');
  
  greet('太郎');
  
  print('5 × 3 = ${multiply(5, 3)}');
}

オプショナル引数

// 名前付きオプショナル引数
void introduce({String name = 'ゲスト', int age = 0}) {
  print('名前: $name, 年齢: $age');
}

// 必須の名前付き引数(Dart 2.12以降)
void registerUser({required String email, required String password}) {
  print('登録: $email');
}

// 位置指定オプショナル引数
String createMessage(String text, [String suffix = '']) {
  return text + suffix;
}

void main() {
  introduce();                          // 名前: ゲスト, 年齢: 0
  introduce(name: '太郎');              // 名前: 太郎, 年齢: 0
  introduce(name: '花子', age: 25);    // 名前: 花子, 年齢: 25
  
  registerUser(email: 'test@example.com', password: 'secret');
  
  print(createMessage('こんにちは'));           // こんにちは
  print(createMessage('こんにちは', '!'));    // こんにちは!
}

関数を変数に代入

void main() {
  // 関数を変数に代入
  var myFunction = (int x, int y) => x + y;
  print('結果: ${myFunction(10, 20)}');
  
  // 関数を引数として渡す
  void execute(int a, int b, Function operation) {
    print('実行結果: ${operation(a, b)}');
  }
  
  execute(5, 3, (x, y) => x + y);  // 実行結果: 8
  execute(5, 3, (x, y) => x * y);  // 実行結果: 15
}

再帰関数

// 階乗を計算する再帰関数
int factorial(int n) {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
}

// フィボナッチ数列
int fibonacci(int n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

void main() {
  print('5の階乗: ${factorial(5)}');      // 120
  print('フィボナッチ(10): ${fibonacci(10)}');  // 55
}

コメントとドキュメンテーション

コメントの種類

// これは一行コメントです

/*
  これは
  複数行
  コメントです
*/

/// これはドキュメンテーションコメントです
/// APIドキュメントに表示されます
void exampleFunction() {
  print('関数の実行');
}

void main() {
  // 変数の宣言
  var message = 'Hello'; // 行末コメント
  
  /* 一時的に無効化
  print('この行は実行されません');
  */
  
  print(message);
}

ドキュメンテーションコメント

/// ユーザー情報を表すクラス
/// 
/// このクラスは名前と年齢を保持します。
/// 使用例:
/// ```dart
/// var user = User('太郎', 25);
/// user.introduce();
/// ```
class User {
  /// ユーザーの名前
  String name;
  
  /// ユーザーの年齢
  int age;
  
  /// コンストラクタ
  /// 
  /// [name] ユーザーの名前
  /// [age] ユーザーの年齢(0以上)
  User(this.name, this.age);
  
  /// 自己紹介を表示する
  /// 
  /// コンソールに名前と年齢を出力します。
  /// 
  /// 例:
  /// ```dart
  /// user.introduce();
  /// // 出力: 太郎です。25歳です。
  /// ```
  void introduce() {
    print('$nameです。$age歳です。');
  }
}

/// 2つの数値を加算する
/// 
/// [a] と [b] を加算して結果を返します。
/// 
/// Returns: 加算結果
/// 
/// 例:
/// ```dart
/// int result = add(5, 3);  // 8
/// ```
int add(int a, int b) {
  return a + b;
}

void main() {
  var user = User('太郎', 25);
  user.introduce();
  
  print('合計: ${add(10, 20)}');
}

ドキュメンテーションのベストプラクティス

/// 良いドキュメンテーションの例
/// 
/// このクラスは[User]情報を管理します。
/// 詳細は公式ドキュメント参照: https://example.com/docs
/// 
/// **重要:** 年齢は必ず0以上にしてください。
/// 
/// 使用可能なメソッド:
/// * [updateAge] - 年齢を更新
/// * [isAdult] - 成人かどうかを判定
/// 
/// See also:
/// * [Address] クラス
/// * [Contact] クラス
class UserProfile {
  String name;
  int age;
  
  UserProfile(this.name, this.age);
  
  /// 年齢を更新する
  /// 
  /// [newAge]は0以上である必要があります。
  /// 
  /// Throws:
  /// * [ArgumentError] 年齢が負の場合
  void updateAge(int newAge) {
    if (newAge < 0) {
      throw ArgumentError('年齢は0以上にしてください');
    }
    age = newAge;
  }
  
  /// 成人(18歳以上)かどうかを判定
  /// 
  /// Returns: 成人の場合true、未成年の場合false
  bool isAdult() => age >= 18;
}

これで第2章「基本文法」の解説は完了です。これらの基礎をしっかり理解することで、より複雑なDartプログラムを書く準備が整います。次の章では、コレクション(List、Set、Map)について学んでいきましょう!

No responses yet

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です