ゲッターとセッター
CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 28/104。
クラスメンバが private である場合、外部のコードからそれらに直接アクセスすることはできません。ゲッター (getters) と セッター (setters) は、これらの private メンバへの制御されたアクセスを提供する public メソッドです。ゲッターは値を取得し、セッターは値を変更します。
class Temperature {
double celsius; // プライベート - 直接アクセスできません
public:
// ゲッター - 値を返します
double getCelsius() const {
return celsius;
}
// セッター - バリデーション(検証)を行って値を変更します
void setCelsius(double value) {
if (value >= -273.15) { // 絶対零度のチェック
celsius = value;
}
}
};セッターの真の力はバリデーションにあります。
任意の値を代入できるようにする代わりに、ルールを強制することができます。上記の例では、絶対零度を下回る温度は拒否されます。セッターがなければ、誰でも無効なデータを直接代入できてしまいます。
ゲッターは、データを返す前に変換することもできます:
class Temperature {
double celsius;
public:
double getCelsius() const { return celsius; }
// 計算されたゲッター - 華氏を保存せず、計算します
double getFahrenheit() const {
return celsius * 9.0 / 5.0 + 32.0;
}
void setCelsius(double value) { celsius = value; }
};ゲッターにある const キーワードに注目してください。これは、それらがオブジェクトを変更しないことを示しています。セッターの目的はメンバ値を変更することであるため、const にすることはできません。ゲッターとセッターを使用するこのパターンはカプセル化の基本であり、クラスデータがどのようにアクセスされ、変更されるかを完全に制御することができます。
チャレンジ
簡単ゲッターとセッターが、バリデーションや計算済みプロパティを含め、どのようにプライベートデータへの制御されたアクセスを提供するかを実証するプレイヤープロファイルシステムを構築しましょう。
コードを整理するために2つのファイルを作成します:
Player.h: 保護されたデータアクセスを備えたゲームキャラクターのプロファイルを管理するPlayerクラスを定義します。クラスには以下を含める必要があります:- プライベートメンバ:
name(string)、level(int)、experience(int) - 名前を受け取り、
levelを1に、experienceを0に初期化するコンストラクタ - プレイヤーの名前を返すゲッター
getName() - 現在のレベルを返すゲッター
getLevel() - 現在の経験値を返すゲッター
getExperience() - 少なくとも3文字以上の名前のみを受け付けるセッター
setName()— 無効な場合は現在の名前を変更せずに保持します - 正の値のみを受け付けるセッター
addExperience(int points)。経験値が100以上に達すると、プレイヤーはレベルアップします:レベルを1増やし、経験値から100を引きます。十分な経験値が追加された場合、これは複数回発生する可能性があります。 - 次のレベルに到達するために必要な経験値(常に
100 - current experience)を返す計算済みゲッターgetExperienceToNextLevel()
すべてのゲッターはオブジェクトを変更しないため、
constとしてマークしてください。- プライベートメンバ:
main.cpp: ゲッターとセッターの動作を実証します。入力からプレイヤー名と追加する経験値を読み取り(それぞれ別の行)、以下の処理を行います:- 入力された名前で
Playerを作成します "Player: <name>, Level: <level>, XP: <experience>"と出力しますaddExperience()を使用して入力された経験値を追加します- 更新された状態を表示するために、同じステータス行を再度出力します
"XP to next level: <amount>"と出力します- 名前を
"Al"に変更しようとします(バリデーションに失敗するはずです) "Name after invalid change: <name>"と出力します- 名前を
"Champion"に変更します(成功するはずです) "Name after valid change: <name>"と出力します
- 入力された名前で
経験値の入力は文字列として提供されるため、整数に変換する必要があります。#include "Player.h" を使用して、main.cpp にヘッダーファイルをインクルードしてください。
チートシート
ゲッターとセッターは、プライベートなクラスメンバへの制御されたアクセスを提供するパブリックメソッドです。
基本的なゲッターとセッターのパターン:
class Temperature {
double celsius; // プライベートメンバ
public:
// ゲッター - 値を返す (const 修飾)
double getCelsius() const {
return celsius;
}
// セッター - 値を変更する
void setCelsius(double value) {
celsius = value;
}
};バリデーション付きのセッター:
void setCelsius(double value) {
if (value >= -273.15) { // 設定前にバリデーションを行う
celsius = value;
}
}計算されたゲッター:
// 保存せずに計算された値を返す
double getFahrenheit() const {
return celsius * 9.0 / 5.0 + 32.0;
}重要なポイント:
- ゲッターはオブジェクトを変更しないため、
constを付けるべきです - セッターはメンバ値を変更するため、
constにすることはできません - セッターを使用すると、無効なデータを防ぐためのバリデーションが可能になります
- ゲッターは値を返す前に変換したり計算したりすることができます
自分で試してみよう
#include <iostream>
#include <string>
#include "Player.h"
using namespace std;
int main() {
// プレイヤー名を読み込む
string playerName;
getline(cin, playerName);
// 追加する経験値を読み込む(文字列として読み込み、int型に変換する)
string expString;
getline(cin, expString);
int expToAdd = stoi(expString);
// TODO: 入力された名前で Player を作成する
// TODO: 初期ステータスを表示する: "Player: <name>, Level: <level>, XP: <experience>"
// TODO: addExperience() を使用して、入力された経験値を追加する
// TODO: 更新されたステータス行を表示する
// TODO: "XP to next level: <amount>" を表示する
// TODO: 名前を "Al" に変更してみる(バリデーションに失敗するはず)
// TODO: "Name after invalid change: <name>" を表示する
// TODO: 名前を "Champion" に変更する(成功するはず)
// TODO: "Name after valid change: <name>" を表示する
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
3コンストラクタとデストラクタ
デフォルトコンストラクタ引数付きコンストラクタコピーコンストラクタムーブコンストラクタコンストラクタ初期化リスト委譲コンストラクタデストラクタ詳解Rule of Three / Five / Zeroまとめ - Stringクラス6演算子オーバーロード
演算子オーバーロード入門算術演算子のオーバーロード比較演算子のオーバーロードストリーム演算子代入演算子のオーバーロード[] と () 演算子のオーバーロード型変換演算子まとめ:Matrix クラス