Getter & Setter メソッド
CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 49/107。
エクスポートされていないフィールドはパッケージの外から直接アクセスできないため、制御されたアクセスを可能にするメソッドを提供する必要があります。これらは一般的にゲッター(getters)およびセッター(setters)と呼ばれます。
Goにおいて、ゲッターの慣習はシンプルです:フィールド名の先頭を大文字にして使用します。「Get」を接頭辞として付けないでください。GetBalance()ではなく、単にBalance()を使用します:
type BankAccount struct {
balance int // エクスポートされていない
}
// ゲッター - 値を返します
func (b *BankAccount) Balance() int {
return b.balance
}
// セッター - バリデーションを伴って値を変更します
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}
セッターの真の力は、バリデーションやビジネスロジックを追加することにあります。外部のコードに任意の値を直接設定させるのではなく、何が許可されるかを制御できます:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}
この Deposit メソッドは、負の預け入れを許可しないというルールを強制する、特殊なセッターとして機能します。外部のコードは必ずメソッドを経由する必要があり、これにより構造体が常に有効な状態に保たれることが保証されます。これはカプセル化の実践です。つまり、データを隠蔽しながら、制御された振る舞いのみを公開しているのです。
チャレンジ
簡単ゲッターとセッターメソッドを使用した適切なカプセル化を実証する温度変換器を作成しましょう。内部的に温度を摂氏(Celsius)で保持し、バリデーションを伴うメソッドを通じて制御されたアクセスを提供する構造体を作成します。
コードは2つのファイルに分けて構成します:
temperature.go: 外部に公開されないcelsiusフィールド(float64)を持つTemperature構造体を作成します。以下のメソッドを実装してください:Celsius()- 現在の摂氏温度を返すゲッターSetCelsius(value float64)- 絶対零度(-273.15)以上の値のみを受け入れるセッター。値がこの閾値を下回る場合、温度は変更されないようにします。Fahrenheit()-(celsius * 9/5) + 32の公式を使用して、温度を華氏(Fahrenheit)に変換して返します。SetFahrenheit(value float64)- 入力された華氏を摂氏に変換して保存しますが、変換後の摂氏の値が -273.15 以上の場合のみ保存します。
NewTemperature(celsius float64) *Temperatureを追加してください(コンストラクタへの入力は有効な値であると仮定します)。main.go: 入力から温度値を読み取り、ゲッター/セッターメソッドを実演します。温度を作成し、両方の単位で値を表示した後、新しい値を設定しようと試みてその結果を表示します。
以下の入力が提供されます:
- 1行目: 初期の摂氏(Celsius)の値
- 2行目: 新しく設定する摂氏(Celsius)の値
- 3行目: 新しく設定する華氏(Fahrenheit)の値
すべての温度出力は小数点以下2桁でフォーマットしてください。以下の順序で出力します:
- 作成後:
C: [celsius] F: [fahrenheit] - 摂氏設定後:
C: [celsius] F: [fahrenheit] - 華氏設定後:
C: [celsius] F: [fahrenheit]
例えば、25、-300、212 が与えられた場合、出力は以下のようになります:
C: 25.00 F: 77.00
C: 25.00 F: 77.00
C: 100.00 F: 212.002行目の値が変更されていないのは、-300 が絶対零度を下回っているため、セッターが拒否したからです。3行目は、212°F(100°Cに変換されます)の設定に成功した後の温度を示しています。これがセッターの力です。セッターは、データの妥当性を維持するためのルールを強制します。
チートシート
非公開(Unexported)フィールドをパッケージ外から制御してアクセスするには、ゲッター(getter)とセッター(setter)メソッドが必要です。
ゲッターの慣習
Goでは、ゲッターにはフィールド名の先頭を大文字にした名前を使用します。"Get"というプレフィックスは付けません:
type BankAccount struct {
balance int // 非公開
}
// ゲッター - 値を返す
func (b *BankAccount) Balance() int {
return b.balance
}バリデーション付きのセッター
セッターは値を変更し、バリデーションやビジネスロジックを含めることができます:
// セッター - バリデーションを行って値を変更する
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}特化したセッター
直接値を代入させるのではなく、特定のルールを強制するメソッドを作成します:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}このアプローチによりカプセル化が保証されます。データを隠蔽しつつ制御された振る舞いを公開することで、構造体を有効な状態に保つことができます。
自分で試してみよう
package main
import (
"fmt"
)
func main() {
// 入力値を読み込む
var initialCelsius float64
var newCelsius float64
var newFahrenheit float64
fmt.Scanln(&initialCelsius)
fmt.Scanln(&newCelsius)
fmt.Scanln(&newFahrenheit)
// TODO: コンストラクタを使用して新しい Temperature を作成する
// TODO: 初期値を "C: [celsius] F: [fahrenheit]" の形式で小数点以下2桁まで出力する
// TODO: 新しい Celsius の値の設定を試み、結果を出力する
// TODO: 新しい Fahrenheit の値の設定を試み、結果を出力する
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
1Go オブジェクト指向の基礎
外部ファイルGo ワークスペースとモジュールパッケージとインポート公開された名前と非公開の名前Go におけるオブジェクト指向入門クラスとしての構造体構造体へのメソッド定義ポインタレシーバと値レシーバ構造体の初期化コンストラクタ関数まとめ:簡易計算機8エラー処理とOOP
error インターフェースカスタムエラー型エラーラッピング (fmt.Errorf)センチネルエラーerrors.Is() と errors.As()Panic、Defer、Recover復習 - ファイルパーサー