Gettery i settery
Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 28 z 104.
Gdy składowe klasy są prywatne, kod zewnętrzny nie może uzyskać do nich bezpośredniego dostępu. Gettery i settery to publiczne metody zapewniające kontrolowany dostęp do tych prywatnych składowych — gettery pobierają wartości, a settery je modyfikują.
class Temperature {
double celsius; // Prywatne — nie można uzyskać bezpośredniego dostępu
public:
// Getter — zwraca wartość
double getCelsius() const {
return celsius;
}
// Setter — zmienia wartość po sprawdzeniu jej poprawności
void setCelsius(double value) {
if (value >= -273.15) { // Sprawdzenie zera bezwzględnego
celsius = value;
}
}
};Prawdziwa moc metod ustawiających polega na walidacji.
Zamiast pozwalać na przypisanie dowolnej wartości, możesz narzucić reguły. W powyższym przykładzie odrzucane są temperatury poniżej zera absolutnego. Bez settera każdy mógłby bezpośrednio przypisać nieprawidłowe dane.
Gettery mogą również przekształcać dane przed ich zwróceniem:
class Temperature {
double celsius;
public:
double getCelsius() const { return celsius; }
// Getter obliczający wartość - nie przechowuje temperatury w stopniach Fahrenheita, lecz ją oblicza
double getFahrenheit() const {
return celsius * 9.0 / 5.0 + 32.0;
}
void setCelsius(double value) { celsius = value; }
};Zwróć uwagę na słowo kluczowe const przy metodach pobierających — oznacza ono, że nie modyfikują one obiektu. Metody ustawiające nie mogą być oznaczone jako const, ponieważ ich celem jest zmiana wartości składowych. Ten wzorzec używania metod pobierających i ustawiających ma fundamentalne znaczenie dla enkapsulacji, dając ci pełną kontrolę nad tym, jak uzyskuje się dostęp do danych klasy i jak się je modyfikuje.
Wyzwanie
ŁatwyZbudujmy system profilu gracza, który pokaże, jak metody pobierające i ustawiające zapewniają kontrolowany dostęp do prywatnych danych, w tym walidację i właściwości obliczane.
Utworzysz dwa pliki, aby uporządkować swój kod:
Player.h: Zdefiniuj klasęPlayer, która zarządza profilem postaci w grze z chronionym dostępem do danych. Twoja klasa powinna zawierać:- Prywatne składowe:
name(string),level(int) iexperience(int) - Konstruktor, który przyjmuje nazwę i inicjalizuje
levelwartością1, aexperiencewartością0 - Metodę pobierającą
getName(), która zwraca imię gracza - Metodę pobierającą
getLevel(), która zwraca aktualny poziom - Metodę pobierającą
getExperience(), która zwraca aktualne punkty doświadczenia - Metodę ustawiającą
setName(), która akceptuje tylko nazwy mające co najmniej 3 znaki; jeśli nazwa jest nieprawidłowa, pozostaw aktualną nazwę bez zmian - Metodę ustawiającą
addExperience(int points), która akceptuje tylko wartości dodatnie. Gdy doświadczenie osiągnie lub przekroczy100, gracz awansuje na kolejny poziom: zwiększ poziom o 1 i odejmij 100 od doświadczenia. Może się to zdarzyć wielokrotnie, jeśli dodano wystarczająco dużo doświadczenia. - Obliczaną metodę pobierającą
getExperienceToNextLevel(), która zwraca, ile punktów doświadczenia brakuje do osiągnięcia kolejnego poziomu (zawsze100 - current experience)
Oznacz wszystkie metody pobierające jako
const, ponieważ nie modyfikują obiektu.- Prywatne składowe:
main.cpp: Pokaż działanie metod pobierających i ustawiających. Wczytaj z wejścia imię gracza i liczbę punktów doświadczenia do dodania (każde w osobnym wierszu), a następnie:- Utwórz obiekt
Playerz wczytanym imieniem - Wypisz
"Player: <name>, Level: <level>, XP: <experience>" - Dodaj wczytane punkty doświadczenia za pomocą
addExperience() - Ponownie wypisz ten sam wiersz statusu, aby pokazać zaktualizowany stan
- Wypisz
"XP to next level: <amount>" - Spróbuj zmienić imię na
"Al"(walidacja powinna się nie powieść) - Wypisz
"Name after invalid change: <name>" - Zmień imię na
"Champion"(powinno się udać) - Wypisz
"Name after valid change: <name>"
- Utwórz obiekt
Dane wejściowe dotyczące doświadczenia zostaną podane jako ciąg znaków, który trzeba będzie przekonwertować na liczbę całkowitą. Dołącz plik nagłówkowy w main.cpp za pomocą #include "Player.h".
Spróbuj swoich sił
#include <iostream>
#include <string>
#include "Player.h"
using namespace std;
int main() {
// Wczytaj imię gracza
string playerName;
getline(cin, playerName);
// Wczytaj punkty doświadczenia do dodania (jako string, przekonwertuj na int)
string expString;
getline(cin, expString);
int expToAdd = stoi(expString);
// TODO: Utwórz obiekt Player z wczytanym imieniem
// TODO: Wypisz stan początkowy: "Player: <name>, Level: <level>, XP: <experience>"
// TODO: Dodaj wczytane punkty doświadczenia za pomocą addExperience()
// TODO: Wypisz zaktualizowany wiersz stanu
// TODO: Wypisz "XP to next level: <amount>"
// TODO: Spróbuj zmienić imię na "Al" (walidacja powinna zakończyć się niepowodzeniem)
// TODO: Wypisz "Name after invalid change: <name>"
// TODO: Zmień imię na "Champion" (powinno się udać)
// TODO: Wypisz "Name after valid change: <name>"
return 0;
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneBudowanie i kompilacja C++Pliki nagłówkowe i pliki źródłowePrzestrzenie nazw i zakresWprowadzenie do programowania obiektowego w C++Klasy a obiektyWskaźnik „this”Metody (funkcje składowe)Atrybuty (składowe danych)Podstawy konstruktorów i destruktorówPowtórzenie – prosty kalkulator4Właściwości klas
Elementy instancji a elementy statyczneGettery i setteryStałe funkcje składoweSłowo kluczowe mutableMetody i zmienne statyczneFunkcje i klasy zaprzyjaźnionePodsumowanie – menedżer konta bankowego7Dziedziczenie
Podstawy dziedziczeniaPoziomy dostępu w dziedziczeniuKolejność wywołań konstruktora i destruktoraNadpisywanie metodFunkcje wirtualne i VTableWielokrotne dziedziczenieDziedziczenie wirtualnePowtórzenie — hierarchia pracowników2Zarządzanie pamięcią
Pamięć stosu a stertyWskaźniki i referencjePamięć dynamiczna (new/delete)Inteligentne wskaźniki w C++RAII w C++Podsumowanie — menedżer tablicy dynamicznej5Hermetyzacja
Specyfikatory dostępu w C++Specyfikatory dostępu — szczegółowoUkrywanie informacjiStruktura a klasaKlasy zagnieżdżone i wewnętrznePodsumowanie — system ewidencji studentów8Polimorfizm
Polimorfizm czasu kompilacji i wykonaniaPrzeciążanie funkcjiFunkcje wirtualne — powtórkaCzysto wirtualne funkcjeKlasy abstrakcyjneProjektowanie interfejsów w C++Rzutowanie dynamiczne i RTTIPodsumowanie — kalkulator kształtów3Konstruktory i destruktory
Konstruktor domyślnyKonstruktor z parametramiKonstruktor kopiującyKonstruktor przenoszącyListy inicjalizacyjne konstruktoraKonstruktory delegująceDestruktor — szczegółowe omówienieZasada trzech / pięciu / zeraPodsumowanie — klasa String6Przeciążanie operatorów
Wprowadzenie do przeciążania operatorówPrzeciążanie operatorów arytmetycznychPrzeciążanie operatorów porównaniaOperatory strumieniowePrzeciążanie operatora przypisaniaPrzeciążanie operatorów [] i ()Operatory konwersji typówPodsumowanie — klasa Matrix9Szablony
Szablony funkcjiSzablony klasSpecjalizacja szablonówSzablony wariadycznePodstawy SFINAE i cech typówPodsumowanie — kontener generycznyPoćwicz samodzielnie: Kompilator C++ online