Getter と Setter の詳細
CoddyのDartジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 33/110。
ゲッターとセッターは、プライベートフィールドと組み合わせることで、カプセル化のための強力なツールになります。これらを使用すると、データのアクセスや変更方法を完全に制御しながら、クリーンなパブリックインターフェースを公開できます。
一般的なパターンは、プライベートフィールドを、バリデーション(検証)を含む公開のゲッターおよびセッターと組み合わせることです。
class Temperature {
double _celsius = 0;
double get celsius => _celsius;
set celsius(double value) {
if (value < -273.15) {
_celsius = -273.15; // 絶対零度が最小値
} else {
_celsius = value;
}
}
}セッターはビジネスルールを適用し、オブジェクトが不正な状態にならないようにすることができます。
プライベートデータから値を派生させる計算ゲッターを作成することもできます:
class Rectangle {
double _width;
double _height;
Rectangle(this._width, this._height);
double get area => _width * _height; // 計算値
double get perimeter => 2 * (_width + _height);
double get width => _width;
set width(double value) {
if (value > 0) _width = value;
}
}読み取り専用のアクセスが必要な場合があります。その場合は、セッターを定義せずにゲッターだけを提供します。
class Order {
final DateTime _createdAt = DateTime.now();
DateTime get createdAt => _createdAt; // 読み取り専用
}このパターンは、外部コードにデータへの可視性を提供しながら、いかなる変更も防ぎます。プライベートフィールドとゲッターのみを組み合わせることで、真の読み取り専用アクセスが実現します。
チャレンジ
簡単データアクセスを制御するためのゲッターとセッターの威力を示す、製品在庫システムを構築しましょう。内部データを保護しながら、計算プロパティとバリデーションを提供するクラスを作成します。
コードを2つのファイルに整理します:
product.dart: 適切なカプセル化を行って在庫を管理するProductクラスを定義します。製品には以下のものを含める必要があります:- パブリックな
String name - プライベートな
double _price - プライベートな
int _quantity - これら3つの値を受け取るコンストラクタ
- プライベートな価格を返すゲッター
price 0より大きい値のみを受け入れるセッターprice(無効な値は無視する)- プライベートな数量を返すゲッター
quantity 0以上の値のみを受け入れるセッターquantity(負の値は無視する)_price * _quantityを返す計算ゲッターtotalValue- 数量が
0より大きい場合にtrueを返す計算ゲッターisInStock - 名前の最初の3文字を大文字にし、その後に数量を続けたシンプルなSKUを生成する読み取り専用ゲッター
sku(例:数量25の "Laptop" の場合はLAP25) - 製品の詳細を表示するメソッド
displayProduct()
- パブリックな
main.dart: 製品クラスをインポートし、ゲッターとセッターがどのようにアクセスを制御するかを示します:- 名前が
'Laptop'、価格が999.99、数量が25の製品を作成します displayProduct()を呼び出しますIn stock: [isInStock]を出力しますSKU: [sku]を出力します- 価格を
-50.0に設定しようとします(無視されるはずです) - 価格を
899.99に設定します(有効な変更) - 数量を
-10に設定しようとします(無視されるはずです) - 数量を
0に設定します(有効な変更) displayProduct()を呼び出しますIn stock: [isInStock]を出力しますSKU: [sku]を出力します
- 名前が
displayProduct() メソッドは、以下の形式で出力する必要があります:
--- Product Info ---
Name: [name]
Price: $[price]
Quantity: [quantity]
Total Value: $[totalValue]期待される出力:
--- Product Info ---
Name: Laptop
Price: $999.99
Quantity: 25
Total Value: $24999.75
In stock: true
SKU: LAP25
--- Product Info ---
Name: Laptop
Price: $899.99
Quantity: 0
Total Value: $0.0
In stock: false
SKU: LAP0チートシート
ゲッターとセッターをプライベートフィールドと組み合わせることで、カプセル化とデータアクセスへの制御が可能になります。
ゲッターとセッターを持つプライベートフィールド
class Temperature {
double _celsius = 0;
double get celsius => _celsius;
set celsius(double value) {
if (value < -273.15) {
_celsius = -273.15;
} else {
_celsius = value;
}
}
}計算されたゲッター
ゲッターはプライベートデータから値を派生させることができます:
class Rectangle {
double _width;
double _height;
Rectangle(this._width, this._height);
double get area => _width * _height;
double get perimeter => 2 * (_width + _height);
double get width => _width;
set width(double value) {
if (value > 0) _width = value;
}
}読み取り専用アクセス
読み取り専用プロパティには、セッターなしのゲッターを提供します:
class Order {
final DateTime _createdAt = DateTime.now();
DateTime get createdAt => _createdAt;
}自分で試してみよう
import 'product.dart';
void main() {
// TODO: 名前が 'Laptop'、価格が 999.99、数量が 25 の製品を作成してください
// TODO: displayProduct() を呼び出してください
// TODO: "In stock: [isInStock]" を出力してください
// TODO: "SKU: [sku]" を出力してください
// TODO: 価格を -50.0 に設定してみてください(無視されるはずです)
// TODO: 価格を 899.99 に設定してください(有効な変更)
// TODO: 数量を -10 に設定してみてください(無視されるはずです)
// TODO: 数量を 0 に設定してください(有効な変更)
// TODO: displayProduct() を呼び出してください
// TODO: "In stock: [isInStock]" を出力してください
// TODO: "SKU: [sku]" を出力してください
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4Null Safety
Null Safety 入門Nullable と Non-Nullable? 演算子と ! 演算子late キーワードと Null SafetyNull-Aware 演算子クラスにおける Null Safetyまとめ:ユーザープロフィールシステム10コレクションとジェネリクス
List, Set, Map の概要型安全なコレクションジェネリッククラスジェネリックメソッドジェネリクスの制約Iterable と Iteratorまとめ:ジェネリックなストレージ