公開メンバと非公開メンバ
CoddyのDartジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 30/110。
カプセル化は、オブジェクト指向プログラミングの核心的な原則の1つです。これは、クラスの内部データへのアクセスを制御し、何を外部に公開し、何を隠蔽したままにするかを決定することを指します。
Dartでは、クラスメンバー(フィールドとメソッド)はデフォルトで公開(public)されています。これは、どのコードからでも直接アクセスできることを意味します:
class BankAccount {
String owner;
double balance;
BankAccount(this.owner, this.balance);
}
var account = BankAccount('Alice', 1000);
account.balance = -500; // 誰でも直接これを変更できてしまいます!これは問題です。無効な残高を設定することを防ぐ手段が何もありません。
内部データを保護するために、Dartはプライベートメンバーを使用します。名前の先頭にアンダースコア _ が付くと、そのメンバーはプライベートになります:
class BankAccount {
String owner;
double _balance; // プライベート - アンダースコアで始まる
BankAccount(this.owner, this._balance);
double get balance => _balance; // 制御されたアクセス
}これで、_balance はクラスが定義されているライブラリの外から直接アクセスできなくなりました。外部のコードは、代わりに公開ゲッターを使用する必要があります。これにより、データの読み取りや変更の方法を制御でき、オブジェクトが常に有効な状態に保たれることを保証できます。
チャレンジ
簡単パブリックメンバとプライベートメンバの違いを実証する、シンプルなパスワードマネージャーを作成しましょう。アンダースコアの接頭辞によって、クラスのライブラリ外から機密データに直接アクセスされるのをどのように防ぐかを確認します。
コードを整理するために、2つのファイルを作成します:
credential.dart: ウェブサイトのログイン情報を保存するCredentialクラスを定義します。このクラスには以下を含める必要があります:- パブリックな
String website- どのウェブサイト向けのものか誰でも見ることができて構いません - パブリックな
String username- ユーザー名は表示されても構いません - プライベートな
String _password- 実際のパスワードは保護される必要があります - これら3つの値をすべて受け取るコンストラクタ
- プライベートな
_passwordを返すパブリックなゲッターpassword(制御されたアクセス) - すべての文字をアスタリスク
*に置き換えたパスワード(実際のパスワードと同じ長さ)を返すメソッドgetMaskedPassword() - 認証情報を安全に(実際のパスワードではなく、マスクされたパスワードを表示して)出力するメソッド
displayCredential()
- パブリックな
main.dart: 作成したCredentialクラスをインポートし、カプセル化がどのようにパスワードを保護するかを実証します:- ウェブサイト
'github.com'、ユーザー名'dev_user'、パスワード'secret123'の認証情報を作成します - ウェブサイト
'email.com'、ユーザー名'john_doe'、パスワード'myP@ss'の別の認証情報を作成します - それぞれの認証情報に対して
displayCredential()を呼び出し、次にパブリックなゲッターを使用してパスワードの長さにアクセスし、Actual password length: [length]と出力します
- ウェブサイト
displayCredential() メソッドは、以下の形式で出力する必要があります:
--- Credential ---
Website: [website]
Username: [username]
Password: [maskedPassword]期待される出力:
--- Credential ---
Website: github.com
Username: dev_user
Password: *********
Actual password length: 9
--- Credential ---
Website: email.com
Username: john_doe
Password: ******
Actual password length: 6チートシート
カプセル化は、何を表示し、何を隠すべきかを決定することで、クラスの内部データへのアクセスを制御します。
Dartでは、クラスのメンバーはデフォルトでパブリックです:
class BankAccount {
String owner;
double balance; // パブリック - 直接アクセス可能
BankAccount(this.owner, this.balance);
}
var account = BankAccount('Alice', 1000);
account.balance = -500; // 直接変更が可能内部データを保護するには、名前にアンダースコア _ を付けることでプライベートメンバーを使用します:
class BankAccount {
String owner;
double _balance; // プライベート - アンダースコアで始まる
BankAccount(this.owner, this._balance);
double get balance => _balance; // ゲッターを介した制御されたアクセス
}プライベートメンバーは、クラスが定義されているライブラリの外から直接アクセスすることはできません。パブリックなゲッターやメソッドを使用してプライベートデータへの制御されたアクセスを提供し、オブジェクトが有効な状態に保たれるようにします。
自分で試してみよう
import 'credential.dart';
void main() {
// TODO: github.com のクレデンシャルを作成する
// website: 'github.com', username: 'dev_user', password: 'secret123'
// TODO: 1つ目のクレデンシャルで displayCredential() を呼び出す
// TODO: 公開ゲッターを使用して実際のパスワードの長さを出力する
// 形式: "Actual password length: [length]"
// TODO: email.com のクレデンシャルを作成する
// website: 'email.com', username: 'john_doe', password: 'myP@ss'
// TODO: 2つ目のクレデンシャルで displayCredential() を呼び出す
// TODO: 公開ゲッターを使用して実際のパスワードの長さを出力する
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4Null Safety
Null Safety 入門Nullable と Non-Nullable? 演算子と ! 演算子late キーワードと Null SafetyNull-Aware 演算子クラスにおける Null Safetyまとめ:ユーザープロフィールシステム10コレクションとジェネリクス
List, Set, Map の概要型安全なコレクションジェネリッククラスジェネリックメソッドジェネリクスの制約Iterable と Iteratorまとめ:ジェネリックなストレージ