Menu
Coddy logo textTech

Gettery i settery

Część sekcji Programowanie obiektowe ścieżki C w Coddy. Lekcja 19 z 61.

W przypadku nieprzezroczystych wskaźników składowe struktury są ukryte przed kodem zewnętrznym. Ale jeśli kod zewnętrzny nie może uzyskać bezpośredniego dostępu do danych, jak możemy je odczytywać lub modyfikować? Odpowiedzią są funkcje odczytujące i ustawiające: publiczne interfejsy zapewniające kontrolowany dostęp do prywatnych danych.

Getter zwraca wartość ukrytego składowego:

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

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

Setter modyfikuje ukryty element:

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

Zwróć uwagę na konwencję nazewnictwa: poprzedzaj nazwy funkcji nazwą typu (counter_), aby uniknąć konfliktów i zapewnić przejrzystość API. Gettery używają wskaźników const, ponieważ nie modyfikują obiektu.

Teraz zewnętrzny kod może bezpiecznie korzystać z ukrytych danych:

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

Ten wzorzec daje ci pełną kontrolę nad sposobem dostępu do danych: to podstawa, na której oprzemy się w następnej lekcji, dodając logikę walidacji do setterów.

challenge icon

Wyzwanie

Łatwy

Zbudujmy moduł Score, który wykorzystuje wzorzec nieprzezroczystego wskaźnika z funkcjami pobierającą i ustawiającą. Utworzysz ukryty licznik punktów, z którym kod zewnętrzny będzie mógł wchodzić w interakcję wyłącznie za pośrednictwem udostępnionego przez Ciebie publicznego interfejsu.

Utworzysz trzy pliki:

  • score.h: Twój publiczny interfejs. Zadeklaruj nieprzezroczysty typ Score za pomocą deklaracji wyprzedzającej (bez treści struktury!). Zadeklaruj następujące funkcje:
    • create_score: przyjmuje liczbę całkowitą oznaczającą początkową liczbę punktów i zwraca wskaźnik do Score
    • free_score: przyjmuje wskaźnik do Score i zwalnia pamięć
    • score_get_points: funkcja pobierająca, która przyjmuje const Score * i zwraca bieżącą liczbę punktów
    • score_set_points: funkcja ustawiająca, która przyjmuje Score * i liczbę całkowitą, aktualizując wartość punktów
    Użyj strażników nagłówka z symbolem SCORE_H.
  • score.c: Zdefiniuj właściwą strukturę struct Score z jednym ukrytym polem: int points. Zaimplementuj wszystkie cztery funkcje. Funkcja pobierająca powinna zwracać ukrytą wartość, a funkcja ustawiająca powinna ją aktualizować. Pamiętaj, że funkcje pobierające używają wskaźników const, ponieważ nie modyfikują obiektu.
  • main.c: Zademonstruj działanie modułu, tworząc wynik, odczytując jego wartość, modyfikując ją za pomocą funkcji ustawiającej i ponownie ją odczytując.

Otrzymasz dwa wejścia: początkową liczbę punktów (liczbę całkowitą) oraz nową wartość punktów (liczbę całkowitą), którą należy ustawić.

W pliku głównym utwórz obiekt Score z początkową liczbą punktów, wypisz bieżącą wartość za pomocą funkcji pobierającej, zaktualizuj ją za pomocą funkcji ustawiającej, przekazując nową wartość, wypisz zaktualizowaną wartość, a następnie zwolnij pamięć zajmowaną przez wynik i wypisz potwierdzenie.

Wypisz wynik w tym formacie:

Initial: {points}
Updated: {points}
Freed

Na przykład dla wejść 100 i 250 wynik będzie następujący:

Initial: 100
Updated: 250
Freed

Zwróć uwagę, że main.c nie może uzyskać bezpośredniego dostępu do points. Musi korzystać z funkcji pobierającej i ustawiającej. To właśnie enkapsulacja w praktyce: masz pełną kontrolę nad tym, jak można odczytywać i modyfikować ukryte dane.

Spróbuj swoich sił

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

int main() {
    int initial_points, new_points;
    scanf("%d", &initial_points);
    scanf("%d", &new_points);
    
    // TODO: Utwórz obiekt Score z initial_points
    
    // TODO: Wypisz wartość początkową za pomocą gettera
    // Format: "Initial: {points}"
    
    // TODO: Zaktualizuj wynik za pomocą settera, używając new_points
    
    // TODO: Wypisz zaktualizowaną wartość za pomocą gettera
    // Format: "Updated: {points}"
    
    // TODO: Zwolnij pamięć zajmowaną przez obiekt Score i wypisz "Freed"
    
    return 0;
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C online