Menu
Coddy logo textTech

Validación en setters

Parte de la sección Programación Orientada a Objetos del Journey de C de Coddy. Lección 20 de 61.

En la lección anterior, creamos setters básicos que simplemente asignan valores. Pero esto pasa por alto un beneficio clave de la encapsulación: la capacidad de proteger tus datos añadiendo lógica de validación.

Considera un Counter que nunca debería ser negativo. Sin encapsulación, cualquiera podría escribir c->value = -50 y corromper el estado. Con un setter, controlas qué valores están permitidos:

// counter.c
void counter_set_value(Counter *c, int new_value) {
    if (new_value < 0) {
        return;  // Rechaza la entrada inválida silenciosamente
    }
    c->value = new_value;
}

Ahora los valores negativos simplemente se ignoran.

También podrías optar por devolver un código de estado para indicar éxito o fracaso:

int counter_set_value(Counter *c, int new_value) {
    if (new_value < 0) {
        return 0;  // Fallo
    }
    c->value = new_value;
    return 1;  // Éxito
}

Este patrón permite que quien realiza la llamada sepa si la operación tuvo éxito. La idea clave es que los setters no se limitan a la asignación: son guardianes que hacen cumplir las reglas sobre cuál puede ser el estado de tu objeto. Este es el verdadero poder de la encapsulación: tu objeto mantiene su propia integridad, independientemente de lo que el código externo intente hacer.

challenge icon

Desafío

Fácil

Construyamos un módulo Temperature que proteja sus datos mediante la validación en el setter. Crearás un rastreador de temperatura que solo acepta valores dentro de un rango válido: demostrando cómo los setters actúan como guardianes del estado de tu objeto.

Crearás tres archivos:

  • temperature.h: Tu interfaz pública mediante el patrón de puntero opaco. Declara un tipo Temperature únicamente con una declaración anticipada. Declara estas funciones:
    • create_temperature: recibe un entero para los grados iniciales y devuelve un puntero a Temperature
    • free_temperature: libera la memoria asignada
    • temp_get_degrees: getter que devuelve el valor actual de la temperatura
    • temp_set_degrees: setter que devuelve un int (1 para indicar éxito, 0 para indicar fallo)
    Usa protecciones de inclusión con el símbolo TEMPERATURE_H.
  • temperature.c: Define la struct Temperature real con un miembro int degrees oculto. Implementa todas las funciones. La clave es tu setter. Solo debe aceptar valores entre -50 y 150 (inclusive). Si el valor está fuera de este rango, devuelve 0 y deja la temperatura sin cambios. Si es válido, actualiza el valor y devuelve 1.
  • main.c: Demuestra la validación intentando establecer temperaturas válidas y no válidas, mostrando que los valores no válidos se rechazan mientras que los válidos se aceptan.

Recibirás tres entradas: la temperatura inicial, una temperatura válida que establecer (dentro del rango) y una temperatura no válida que intentar establecer (fuera del rango).

En tu archivo principal, crea un Temperature con el valor inicial e imprímelo. Después, intenta establecer la temperatura no válida, ya que debería rechazarse; imprime el resultado y muestra que el valor permanece sin cambios. Finalmente, establece la temperatura válida, imprime el resultado de éxito y muestra el valor actualizado. Libera la memoria y confirma la limpieza.

Imprime la salida con este formato:

Initial: {degrees}
Set {invalid}: {0 or 1}
After invalid: {degrees}
Set {valid}: {0 or 1}
After valid: {degrees}
Freed

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

Initial: 25
Set 200: 0
After invalid: 25
Set 100: 1
After valid: 100
Freed

Esto demuestra el verdadero poder de la encapsulación. Tu setter aplica las reglas sobre lo que constituye una temperatura válida, protegiendo la integridad del objeto independientemente de los valores que el código externo intente asignar.

Pruébalo tú mismo

#include <stdio.h>
#include "temperature.h"

int main() {
    // Leer entradas
    int initial, valid_temp, invalid_temp;
    scanf("%d", &initial);
    scanf("%d", &valid_temp);
    scanf("%d", &invalid_temp);
    
    // TODO: Crea un Temperature con el valor inicial
    
    // TODO: Imprime la temperatura inicial
    // Formato: "Initial: {degrees}"
    
    // TODO: Intenta establecer la temperatura inválida
    // Imprime el resultado y muestra que el valor permanece sin cambios
    // Formato: "Set {invalid}: {0 or 1}"
    // Format: "After invalid: {degrees}"
    
    // TODO: Establece la temperatura válida
    // Imprime el resultado exitoso y muestra el valor actualizado
    // Formato: "Set {valid}: {0 or 1}"
    // Formato: "After valid: {degrees}"
    
    // TODO: Libera la memoria e imprime "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 Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C online