Menu
Coddy logo textTech

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.

challenge icon

Desafío

Fácil

Vamos 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 tipo Score opaco 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 Score
    • free_score — toma un puntero Score y libera la memoria
    • score_get_points — un getter que toma un const Score * y devuelve los puntos actuales
    • score_set_points — un setter que toma un Score * y un entero, actualizando el valor de los puntos
    Usa guardas de inclusión con el símbolo SCORE_H.
  • score.c: Define el struct Score real 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 punteros const ya 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}
Freed

Por ejemplo, con las entradas 100 y 250, la salida sería:

Initial: 100
Updated: 250
Freed

Observa 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;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Object Oriented Programming