Menu
Coddy logo textTech

ゲッターとセッター

CoddyのCジャーニー「Object Oriented Programming」セクションの一部 — レッスン 19/61。

不透明なポインタを使用すると、構造体のメンバは外部のコードから隠蔽されます。しかし、外部のコードがデータに直接アクセスできない場合、どのようにしてデータを読み取ったり変更したりすればよいのでしょうか?その答えは、ゲッター(getter)およびセッター(setter)関数です。これらは、プライベートなデータへの制御されたアクセスを提供する公開インターフェースです。

ゲッターは、隠蔽されたメンバの値を返します:

// counter.h
int counter_get_value(const Counter *c);

// counter.c
int counter_get_value(const Counter *c) {
    return c->value;
}

セッターは、隠蔽されたメンバを変更します:

// 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_)をプレフィックスとして付けます。ゲッターはオブジェクトを変更しないため、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

このパターンは、データへのアクセス方法を完全に制御できるようにします。これは、次のレッスンでセッターにバリデーションロジックを追加する際の基礎となります。

challenge icon

チャレンジ

簡単

ゲッターとセッター関数を使用した不透明ポインタ(opaque pointer)パターンを用いる Score モジュールを構築しましょう。外部コードが提供されたパブリックインターフェースを通じてのみデータとやり取りできる、隠蔽されたスコアトラッカーを作成します。

以下の3つのファイルを作成します:

  • score.h: パブリックインターフェースです。前方宣言(構造体の本体なし!)を使用して不透明な Score 型を宣言します。以下の関数を宣言してください:
    • create_score — 初期ポイントの整数を受け取り、Score ポインタを返します
    • free_score — Score ポインタを受け取り、メモリを解放します
    • score_get_pointsconst Score * を受け取り、現在のポイントを返すゲッターです
    • score_set_pointsScore * と整数を受け取り、ポイントの値を更新するセッターです
    インクルードガードにはシンボル SCORE_H を使用してください。
  • score.c: 隠蔽された単一のメンバ int points を持つ実際の struct Score を定義します。4つの関数すべてを実装してください。ゲッターは隠蔽された値を返し、セッターはそれを更新する必要があります。ゲッターはオブジェクトを変更しないため、const ポインタを使用することを忘れないでください。
  • main.c: スコアを作成し、その値を読み取り、セッターを通じて変更し、再度読み取ることでモジュールを実演します。

2つの入力を受け取ります:初期ポイント(整数)と、設定する新しいポイント値(整数)です。

メインファイルで、初期ポイントを使用して Score を作成し、ゲッターを使用して現在の値を表示し、セッターを使用して新しい値で更新し、更新された値を表示した後、スコアを解放して確認メッセージを表示します。

出力は以下の形式で表示してください:

Initial: {points}
Updated: {points}
Freed

例えば、入力が 100250 の場合、出力は以下のようになります:

Initial: 100
Updated: 250
Freed

main.cpoints に直接アクセスできず、必ずゲッターとセッター関数を経由しなければならない点に注目してください。これがカプセル化の実践です。隠蔽されたデータがどのように読み取られ、変更されるかを正確に制御できます。

チートシート

不透明ポインタ(opaque pointers)を使用すると、構造体のメンバは外部コードから隠蔽されます。このプライベートデータにアクセスしたり変更したりするには、ゲッター(getter)関数とセッター(setter)関数を使用します。

ゲッターは隠蔽されたメンバの値を返し、オブジェクトを変更しないため const ポインタを使用します。

// counter.h
int counter_get_value(const Counter *c);

// counter.c
int counter_get_value(const Counter *c) {
    return c->value;
}

セッターは隠蔽されたメンバを変更します。

// 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_)とする命名規則を使用してください。

外部コードは、これらの関数を通じて隠蔽されたデータとやり取りします。

// 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

自分で試してみよう

#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: ゲッターを使用して初期値を出力する
    // 形式: "Initial: {points}"
    
    // TODO: new_points を使用してセッターでスコアを更新する
    
    // TODO: ゲッターを使用して更新された値を出力する
    // 形式: "Updated: {points}"
    
    // TODO: スコアを解放し、"Freed" と出力する
    
    return 0;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

Object Oriented Programmingのすべてのレッスン