게터와 세터
Coddy C 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 61개 중 19번째.
불투명 포인터(opaque pointers)를 사용하면 구조체의 멤버가 외부 코드로부터 숨겨집니다. 하지만 외부 코드에서 데이터에 직접 접근할 수 없다면, 어떻게 데이터를 읽거나 수정할 수 있을까요? 그 답은 getter 및 setter 함수입니다. 이는 비공개 데이터에 대한 제어된 접근을 제공하는 공개 인터페이스입니다.
게터(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
이 패턴은 데이터에 액세스하는 방식에 대한 완전한 제어권을 제공합니다. 이는 다음 레슨에서 세터(setters)에 유효성 검사 로직을 추가할 때 활용할 기초가 됩니다.
챌린지
쉬움게터(getter)와 세터(setter) 함수를 포함한 불투명 포인터(opaque pointer) 패턴을 사용하는 Score 모듈을 만들어 봅시다. 외부 코드에서 여러분이 제공하는 공개 인터페이스를 통해서만 데이터와 상호작용할 수 있는 숨겨진 점수 추적기를 만들게 됩니다.
세 개의 파일을 생성해야 합니다:
score.h: 공개 인터페이스입니다. 전방 선언(forward declaration)을 사용하여 구조체 본문 없이 불투명한Score타입을 선언하세요. 다음 함수들을 선언하십시오:create_score— 초기 점수를 위한 정수를 인자로 받아 Score 포인터를 반환합니다.free_score— Score 포인터를 인자로 받아 메모리를 해제합니다.score_get_points—const Score *를 인자로 받아 현재 점수를 반환하는 게터입니다.score_set_points—Score *와 정수를 인자로 받아 점수 값을 업데이트하는 세터입니다.
SCORE_H심볼을 사용하여 인클루드 가드(include guards)를 적용하세요.score.c: 단일 숨겨진 멤버인int points를 가진 실제struct Score를 정의하세요. 네 가지 함수를 모두 구현하십시오. 게터는 숨겨진 값을 반환해야 하며, 세터는 그 값을 업데이트해야 합니다. 게터는 객체를 수정하지 않으므로const포인터를 사용한다는 점을 기억하세요.main.c: 점수를 생성하고, 값을 읽고, 세터를 통해 수정하고, 다시 읽는 과정을 통해 모듈을 시연하세요.
두 개의 입력을 받게 됩니다: 초기 점수(정수)와 설정할 새로운 점수 값(정수)입니다.
메인 파일에서 초기 점수로 Score를 생성하고, 게터를 사용하여 현재 값을 출력한 다음, 세터를 사용하여 새 값으로 업데이트하고, 업데이트된 값을 출력한 후, 점수 메모리를 해제하고 확인 메시지를 출력하세요.
출력 형식은 다음과 같습니다:
Initial: {points}
Updated: {points}
Freed예를 들어, 입력값이 100과 250인 경우 출력은 다음과 같습니다:
Initial: 100
Updated: 250
Freedmain.c가 points에 직접 접근할 수 없고 반드시 게터와 세터 함수를 거쳐야 한다는 점에 주목하세요. 이것이 바로 캡슐화(encapsulation)의 실제 사례입니다. 여러분은 숨겨진 데이터가 어떻게 읽히고 수정되는지를 정확하게 제어할 수 있습니다.
치트 시트
불투명 포인터(opaque pointers)를 사용하면 구조체 멤버가 외부 코드로부터 숨겨집니다. 이 비공개 데이터에 접근하거나 수정하려면 getter 및 setter 함수를 사용하세요.
getter는 숨겨진 멤버의 값을 반환하며, 객체를 수정하지 않으므로 const 포인터를 사용합니다:
// 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_)로 사용하는 명명 규칙을 사용하세요.
외부 코드는 이러한 함수들을 통해 숨겨진 데이터와 상호작용합니다:
// 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: getter를 사용하여 초기 값 출력
// 형식: "Initial: {points}"
// TODO: new_points와 setter를 사용하여 점수 업데이트
// TODO: getter를 사용하여 업데이트된 값 출력
// 형식: "Updated: {points}"
// TODO: 점수 메모리를 해제하고 "Freed" 출력
return 0;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.