ゲッターとセッター
CoddyのCジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 19/61。
opaque ポインターを使用すると、struct の member は外部のコードから隠されます。しかし、外部のコードがデータに直接アクセスできない場合、どうやってそれを読み取ったり変更したりするのでしょうか?答えは getter 関数と setter 関数です。これらは、private データへの制御されたアクセスを提供する public インターフェースです。
getterは非公開のメンバーの値を返します:
// counter.h
int counter_get_value(const Counter *c);
// counter.c
int counter_get_value(const Counter *c) {
return c->value;
}
setterは非公開のメンバーを変更します。
// counter.h
void counter_set_value(Counter *c, int new_value);
// counter.c
void counter_set_value(Counter *c, int new_value) {
c->value = new_value;
}
命名規則に注目してください。競合を避け、APIを明確にするため、関数名には型名(counter_)を接頭辞として付けています。getterではオブジェクトを変更しないため、constポインターを使用します。
これで、外部コードは隠されたデータと安全にやり取りできます。
// main.c
Counter *c = create_counter(10);
printf("%d\n", counter_get_value(c)); // 10
counter_set_value(c, 25);
printf("%d\n", counter_get_value(c)); // 25
このpatternによって、データへのアクセス方法を完全に制御できます。これは、次のレッスンでセッターに検証ロジックを追加する際に、その上に構築していく基盤となります。
チャレンジ
簡単getter 関数と setter 関数を使用する opaque pointer pattern を使って、Score モジュールを作成しましょう。外部コードが、提供する public interface を通してのみデータを操作できる、隠蔽された score tracker を作成します。
3 つのファイルを作成します。
score.h:public interface です。forward declaration を使用して opaque なScore型を Declare します(struct body は記述しません!)。次の関数を Declare します。create_score:initial points を表す integer を受け取り、Score pointer を returns しますfree_score:Score pointer を受け取り、memory を解放しますscore_get_points:const Score *を受け取り、現在の points を returns する getter ですscore_set_points:Score *と integer を受け取り、points の値を更新する setter です
SCORE_Hシンボルを使用して include guards を実装します。score.c:単一の隠された member であるint pointsを持つ実際のstruct Scoreを Define します。4 つの関数をすべて Implement します。getter は隠された値を return し、setter はその値を更新します。getter は object を変更しないためconstpointer を使用することを Remember してください。main.c:Score を作成し、その値を読み取り、setter を通して変更し、もう一度読み取ることでモジュールを実演します。
2 つの入力を受け取ります。initial points(integer)と、設定する new points value(integer)です。
main file で initial points を使って Score を作成し、getter を使用して現在の値を Print し、setter と new value を使って更新し、更新後の値を Print します。その後、score を Free して確認メッセージを Print します。
次の形式で出力します。
Initial: {points}
Updated: {points}
Freedたとえば、入力が 100 と 250 の場合、出力は次のようになります。
Initial: 100
Updated: 250
Freedmain.c は points に直接アクセスできないことに注目してください。getter と setter の関数を通す必要があります。これが encapsulation の実例です。隠されたデータをどのように読み取り、変更できるかを正確に制御できます。
自分で試してみよう
#include <stdio.h>
#include "score.h"
int main() {
int initial_points, new_points;
scanf("%d", &initial_points);
scanf("%d", &new_points);
// TODO: initial_points で Score を作成する
// TODO: getter を使用して初期値を出力する
// 形式: "Initial: {points}"
// TODO: setter を使用して new_points でスコアを更新する
// TODO: getter を使用して更新後の値を出力する
// 形式: "Updated: {points}"
// TODO: スコアを解放して "Freed" を出力する
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Cオンラインコンパイラ