Menu
Coddy logo textTech

Getters et setters

Fait partie de la section Object Oriented Programming du Journey C de Coddy — leçon 19 sur 61.

Avec les pointeurs opaques, les membres de la structure sont cachés du code externe. Mais si le code externe ne peut pas accéder directement aux données, comment pouvons-nous les lire ou les modifier ? La réponse réside dans les fonctions getter et setter — des interfaces publiques qui fournissent un accès contrôlé aux données privées.

Un getter retourne la valeur d'un membre caché :

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

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

Un setter modifie un membre caché :

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

Remarquez la convention de nommage : préfixez les fonctions avec le nom du type (counter_) pour éviter les conflits et rendre l'API claire. Les getters utilisent des pointeurs const car ils ne modifient pas l'objet.

Désormais, le code externe peut interagir avec les données cachées en toute sécurité :

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

Ce modèle vous donne un contrôle total sur la façon dont les données sont accédées — une base sur laquelle nous nous appuierons dans la prochaine leçon lorsque nous ajouterons une logique de validation aux setters.

challenge icon

Défi

Facile

Construisons un module Score qui utilise le modèle de pointeur opaque avec des fonctions getter et setter. Vous allez créer un suivi de score masqué où le code externe ne peut interagir avec les données qu'à travers l'interface publique que vous fournissez.

Vous allez créer trois fichiers :

  • score.h : Votre interface publique. Déclarez un type Score opaque à l'aide d'une déclaration anticipée (pas de corps de struct !). Déclarez ces fonctions :
    • create_score — prend un entier pour les points initiaux et renvoie un pointeur Score
    • free_score — prend un pointeur Score et libère la mémoire
    • score_get_points — un getter qui prend un const Score * et renvoie les points actuels
    • score_set_points — un setter qui prend un Score * et un entier, mettant à jour la valeur des points
    Utilisez des gardes d'inclusion avec le symbole SCORE_H.
  • score.c : Définissez la structure réelle struct Score avec un seul membre masqué : int points. Implémentez les quatre fonctions. Votre getter doit renvoyer la valeur masquée, et votre setter doit la mettre à jour. Rappelez-vous que les getters utilisent des pointeurs const puisqu'ils ne modifient pas l'objet.
  • main.c : Démontrez votre module en créant un score, en lisant sa valeur, en la modifiant via le setter, puis en la lisant à nouveau.

Vous recevrez deux entrées : les points initiaux (un entier) et la nouvelle valeur de points (un entier) à définir.

Dans votre fichier principal, créez un Score avec les points initiaux, affichez la valeur actuelle à l'aide du getter, mettez-la à jour à l'aide du setter avec la nouvelle valeur, affichez la valeur mise à jour, puis libérez le score et affichez une confirmation.

Affichez la sortie dans ce format :

Initial: {points}
Updated: {points}
Freed

Par exemple, avec les entrées 100 et 250, la sortie serait :

Initial: 100
Updated: 250
Freed

Remarquez comment main.c ne peut pas accéder directement à points — il doit passer par vos fonctions getter et setter. C'est l'encapsulation en action : vous contrôlez exactement comment les données masquées peuvent être lues et modifiées.

Aide-mémoire

Avec les pointeurs opaques, les membres de la structure sont cachés du code externe. Pour accéder à ces données privées ou les modifier, utilisez des fonctions getter et setter.

Un getter renvoie la valeur d'un membre caché et utilise un pointeur const puisqu'il ne modifie pas l'objet :

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

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

Un setter modifie un membre caché :

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

Utilisez une convention de nommage avec le nom du type comme préfixe (counter_) pour éviter les conflits et clarifier l'API.

Le code externe interagit avec les données cachées via ces fonctions :

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

Essayez vous-même

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

int main() {
    int initial_points, new_points;
    scanf("%d", &initial_points);
    scanf("%d", &new_points);
    
    // TODO: Créer un Score avec initial_points
    
    // TODO: Afficher la valeur initiale en utilisant le getter
    // Format : "Initial: {points}"
    
    // TODO: Mettre à jour le score en utilisant le setter avec new_points
    
    // TODO: Afficher la valeur mise à jour en utilisant le getter
    // Format : "Updated: {points}"
    
    // TODO: Libérer le score et afficher "Freed"
    
    return 0;
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Object Oriented Programming