Getters y Setters
Parte de la sección Object Oriented Programming del Journey de C de Coddy — lección 19 de 61.
Con los punteros opacos, los miembros de la estructura están ocultos para el código externo. Pero si el código externo no puede acceder a los datos directamente, ¿cómo los leemos o modificamos? La respuesta son las funciones getter y setter: interfaces públicas que proporcionan un acceso controlado a los datos privados.
Un getter devuelve el valor de un miembro oculto:
// counter.h
int counter_get_value(const Counter *c);
// counter.c
int counter_get_value(const Counter *c) {
return c->value;
}
Un setter modifica un miembro oculto:
// 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;
}
Observe la convención de nomenclatura: anteponga el nombre del tipo a las funciones (counter_) para evitar conflictos y hacer que la API sea clara. Los getters utilizan punteros const, ya que no modifican el objeto.
Ahora el código externo puede interactuar con los datos ocultos de forma segura:
// 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
Este patrón te brinda un control total sobre cómo se accede a los datos —una base sobre la cual construiremos en la próxima lección cuando agreguemos lógica de validación a los setters.
Desafío
FácilVamos a construir un módulo Score que utilice el patrón de puntero opaco con funciones getter y setter. Crearás un rastreador de puntuación oculto donde el código externo solo puede interactuar con los datos a través de la interfaz pública que proporciones.
Crearás tres archivos:
score.h: Tu interfaz pública. Declara un tipoScoreopaco usando una declaración anticipada (¡sin cuerpo de struct!). Declara estas funciones:create_score— toma un entero para los puntos iniciales y devuelve un puntero Scorefree_score— toma un puntero Score y libera la memoriascore_get_points— un getter que toma unconst Score *y devuelve los puntos actualesscore_set_points— un setter que toma unScore *y un entero, actualizando el valor de los puntos
SCORE_H.score.c: Define elstruct Scorereal con un único miembro oculto:int points. Implementa las cuatro funciones. Tu getter debe devolver el valor oculto y tu setter debe actualizarlo. Recuerda que los getters usan punterosconstya que no modifican el objeto.main.c: Demuestra tu módulo creando una puntuación, leyendo su valor, modificándolo a través del setter y leyéndolo de nuevo.
Recibirás dos entradas: los puntos iniciales (un entero) y el nuevo valor de puntos (un entero) a establecer.
En tu archivo principal, crea un Score con los puntos iniciales, imprime el valor actual usando el getter, actualízalo usando el setter con el nuevo valor, imprime el valor actualizado, luego libera el score e imprime una confirmación.
Imprime la salida en este formato:
Initial: {points}
Updated: {points}
FreedPor ejemplo, con las entradas 100 y 250, la salida sería:
Initial: 100
Updated: 250
FreedObserva cómo main.c no puede acceder a points directamente; debe pasar por tus funciones getter y setter. Esto es la encapsulación en acción: tú controlas exactamente cómo se pueden leer y modificar los datos ocultos.
Hoja de referencia
Con los punteros opacos, los miembros de la estructura están ocultos para el código externo. Para acceder o modificar estos datos privados, utilice funciones getter y setter.
Un getter devuelve el valor de un miembro oculto y utiliza un puntero const ya que no modifica el objeto:
// counter.h
int counter_get_value(const Counter *c);
// counter.c
int counter_get_value(const Counter *c) {
return c->value;
}
Un setter modifica un miembro oculto:
// 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;
}
Utilice una convención de nomenclatura con el nombre del tipo como prefijo (counter_) para evitar conflictos y clarificar la API.
El código externo interactúa con los datos ocultos a través de estas funciones:
// 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
Pruébalo tú mismo
#include <stdio.h>
#include "score.h"
int main() {
int initial_points, new_points;
scanf("%d", &initial_points);
scanf("%d", &new_points);
// TODO: Crear un Score con initial_points
// TODO: Imprimir el valor inicial usando el getter
// Formato: "Initial: {points}"
// TODO: Actualizar el score usando el setter con new_points
// TODO: Imprimir el valor actualizado usando el getter
// Formato: "Updated: {points}"
// TODO: Liberar el score e imprimir "Freed"
return 0;
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Object Oriented Programming
1Fundamentos de programación modular
Archivos de cabeceraGuardas de inclusiónArchivos fuenteFunciones estáticasRepaso: Calculadora modular4Encapsulamiento
Concepto de punteros opacosDefinición de structs opacosGetters y SettersValidación en settersResumen: Caja secreta7Punteros a funciones
Declaración de punteros a funcionesLlamada a punteros a funcionesTypedef para punteros a funcionesPasar funciones como argumentosRepaso: Dispatch de calculadora10Contenedores genéricos
Repaso de punteros voidWrapper genéricoSwap genéricoComparación genéricaRepaso: Array genérico2Objetos y métodos
Structs como objetosEl puntero 'Self'Const CorrectnessPuntero vs. ValorMétodos auxiliaresResumen: Point Manager5Proyecto: Cuenta bancaria simple
Configuración del proyectoImplementación de la cuenta3Ciclo de vida de los objetos
Patrón ConstructorPatrón DestructorInicialización en StackCopia profundaResumen: String Wrapper6Herencia mediante composición
Incrustación de StructsLa regla del primer miembroAcceso a miembros padreUpcastingResumen: Jerarquía de formas9Proyecto: Dibujador de figuras
Descripción general del proyectoImplementación del círculo