Dart言語の基本: staticフィールド/メソッドとsetter/getterの解説

Flutter
スポンサーリンク

Dart言語はFlutter開発で使用されるプログラミング言語です。今回は、Dartの基本的な概念であるstaticフィールド/メソッドとsetter/getterについて解説します。

staticフィールド/メソッド

何故staticが必要か?

staticキーワードは、フィールドやメソッドがクラス自体に属することを示します。

これにより、インスタンスを作成せずにアクセスできるようになります。

例1: staticフィールドの使用

class Counter {
  // staticフィールドはクラスに属するため、インスタンス間で共有されます。
  static int count = 0;

  void increment() {
    count++;
  }
}

void main() {
  var counter1 = Counter();
  counter1.increment();
  print(Counter.count); // 1

  var counter2 = Counter();
  counter2.increment();
  print(Counter.count); // 2
}

この例では、countフィールドがクラスに属しているため、異なるインスタンス間で共有されます。

例2: staticメソッドの使用

class MathHelper {
  // staticメソッドはクラスに属するため、インスタンスを作成せずに呼び出せます。
  static int add(int a, int b) {
    return a + b;
  }
}

void main() {
  print(MathHelper.add(3, 4)); // 7
}

ここでは、addメソッドがクラスに属しているため、インスタンスを作成せずに直接呼び出せます。

例3: staticフィールドとメソッドの組み合わせ

class Logger {
  static int logCount = 0;

  // staticメソッド内でstaticフィールドにアクセス
  static void log(String message) {
    print(message);
    logCount++;
  }
}

void main() {
  Logger.log("Hello, World!");
  print(Logger.logCount); // 1
}

この例では、staticメソッド内でstaticフィールドにアクセスしています。

staticフィールド/メソッドがない場合

不具合1: インスタンス間でのデータ共有が困難

staticフィールドがないと、クラスのインスタンス間でデータを共有するのが困難になります。

class Counter {
  int count = 0; // staticでないため、インスタンスごとに異なる値を持つ

  void increment() {
    count++;
  }
}

void main() {
  var counter1 = Counter();
  counter1.increment();
  print(counter1.count); // 1

  var counter2 = Counter();
  counter2.increment();
  print(counter2.count); // 1, しかし期待値は2
}

この例では、countがstaticでないため、counter1counter2のインスタンス間で値が共有されず、期待した結果が得られません。

不具合2: インスタンスの作成なしにメソッドを呼び出せない

staticメソッドがないと、クラスのインスタンスを作成しなければメソッドを呼び出せません。これは、ユーティリティ関数などの場合に非効率です。

setter/getter

何故setter/getterが必要か?

setter/getterは、フィールドへのアクセスを制御するために使用されます。これにより、フィールドへの直接アクセスを制限し、特定のロジックを適用できます。

例1: 基本的なsetter/getter

class Person {
  String _name;

  // getter
  String get name => _name;

  // setter
  set name(String value) {
    _name = value;
  }
}

void main() {
  var person = Person();
  person.name = "John"; // setter
  print(person.name);   // getter, "John"
}

この例では、nameフィールドへのアクセスを制御しています。

例2: setterでのバリデーション

class Age {
  int _value;

  // getter
  int get value => _value;

  // setterで年齢のバリデーション
  set value(int age) {
    if (age >= 0 && age <= 120) {
      _value = age;
    } else {
      print("Invalid age");
    }
  }
}

void main() {
  var age = Age();
  age.value = 25; // Valid
  age.value = -5; // Invalid age
}

ここでは、setterを使用して年齢のバリデーションを行っています。

例3: 計算プロパティのgetter

class Circle {
  double radius;

  // 計算プロパティで円の面積を取得
  double get area => 3.14 * radius * radius;

  Circle(this.radius);
}

void main() {
  var circle = Circle(5.0);
  print(circle.area); // 78.5
}

この例では、計算プロパティを使用して円の面積を取得しています。

setter/getterがない場合

不具合1: フィールドへの直接アクセスによるデータの不整合

setter/getterがないと、フィールドへの直接アクセスが可能になり、データの不整合が生じる可能性があります。

class Age {
  int value; // 直接アクセス可能
}

void main() {
  var age = Age();
  age.value = -5; // 不正な値が設定される
}

この例では、年齢が負の値に設定されるなど、不正な状態になる可能性があります。

不具合2: 計算プロパティの不足

getterを使用しないと、計算プロパティが作成できず、コードの再利用性と可読性が低下する可能性があります。

class Circle {
  double radius;
  // areaの計算プロパティがない
}

void main() {
  var circle = Circle();
  double area = 3.14 * circle.radius * circle.radius; // 円の面積の計算が複数箇所で必要になる場合
}

この例では、円の面積の計算が複数箇所で必要になる場合、コードの重複が生じる可能性があります。

まとめ

staticフィールド/メソッドとsetter/getterは、Dartプログラミングの基本的な概念です。適切に使用することで、コードの再利用性と保守性を向上させることができます。