Lekcja 11. Pola, metody i hermetyzacja (enkapsulacja)
Trudny / egzaminacyjnyPo co się tego uczymy?
Hermetyzacja to jedna z czterech głównych zasad programowania obiektowego (obok dziedziczenia, polimorfizmu i abstrakcji) i pierwsza linia obrony przed błędami — klasa sama pilnuje, żeby jej dane zawsze były w poprawnym, sensownym stanie, niezależnie od tego, kto i jak jej używa.
Teoria
W Lekcji 10 wszystkie pola klasy Film były public — dostępne i modyfikowalne z ZEWNĄTRZ klasy, bez żadnej kontroli. To działa w prostych przykładach, ale w praktyce jest ryzykowne: ktokolwiek może przypisać polu Cena wartość ujemną, co nie ma sensu.
Hermetyzacja (enkapsulacja) to zasada UKRYWANIA wewnętrznych danych obiektu i udostępniania do nich kontrolowanego dostępu — zamiast pozwalać na dowolną, niekontrolowaną zmianę pola, klasa sama decyduje, jakie wartości są dozwolone.
Modyfikatory dostępu:
public — dostępne z dowolnego miejsca w programie.
private — dostępne TYLKO wewnątrz tej samej klasy (domyślny modyfikator pól, jeśli nic nie wpiszesz).
protected — dostępne w tej klasie i w klasach po niej dziedziczących (Lekcja 13).
Właściwości (properties) to standardowy w C# sposób kontrolowanego udostępniania prywatnych pól — wyglądają jak pola z zewnątrz, ale w środku mogą mieć logikę:
private double cena;
public double Cena
{
get { return cena; }
set { if (value >= 0) cena = value; }
}
get określa, co zwrócić przy ODCZYCIE, set określa, co zrobić przy PRZYPISANIU nowej wartości (value to nazwa niosąca przypisywaną wartość) — tutaj blokuje ustawienie ceny ujemnej.
Współczesny C# pozwala też na skrócony zapis prostych właściwości bez dodatkowej logiki: public string Tytul { get; set; } — tzw. auto-property, wygodna, gdy nie potrzebujesz żadnej walidacji.
Przykład z życia
Bankomat nie pozwala Ci bezpośrednio "wpisać" nowego salda na swoim koncie — możesz je zmienić TYLKO przez konkretne, kontrolowane operacje (wpłata, wypłata), z których każda ma swoje zasady. To dokładnie hermetyzacja w praktyce.
Kod (C#)
using System;
class KontoBankowe
{
private double saldo; // prywatne pole - niedostępne bezpośrednio z zewnątrz
public double Saldo
{
get { return saldo; }
private set { saldo = value; } // ustawiać saldo można tylko wewnątrz klasy
}
public void Wplac(double kwota)
{
if (kwota > )
{
Saldo += kwota;
Console.WriteLine("Wpłacono " + kwota + " zł. Saldo: " + Saldo + " zł");
}
}
public void Wyplac(double kwota)
{
if (kwota > && kwota <= Saldo)
{
Saldo -= kwota;
Console.WriteLine("Wypłacono " + kwota + " zł. Saldo: " + Saldo + " zł");
}
else
{
Console.WriteLine("Nie można wypłacić - brak wystarczających środków.");
}
}
}
class Program
{
static void Main()
{
KontoBankowe konto = new KontoBankowe();
konto.Wplac(100);
konto.Wyplac(30);
konto.Wyplac(1000); // odrzucone - za mało środków
// konto.saldo = -50; // BŁĄD KOMPILACJI - pole "saldo" jest prywatne
}
}
Komentarz i wyjaśnienie kodu
Pole saldo jest private — nikt spoza klasy KontoBankowe nie może go odczytać ani zmienić bezpośrednio. Właściwość Saldo udostępnia ODCZYT publicznie (get), ale ZAPIS tylko wewnątrz klasy (private set) — dzięki temu jedynym sposobem zmiany salda z zewnątrz są metody Wplac() i Wyplac(), które PILNUJĄ poprawności operacji (kwota dodatnia, wystarczające środki).
Ćwiczenie samodzielne
Dodaj do klasy KontoBankowe właściwość tylko do odczytu NumerKonta (ustawianą raz, np. w momencie utworzenia obiektu).
Plac zabaw — wypróbuj online
Poniższy kod wykonuje się od razu w Twojej przeglądarce — nic nie trzeba instalować. Zmień kod i kliknij „Uruchom”.
Zadania do pracy własnej
Zdefiniuj klasę
Prostokatz prywatnymi polamiszerokosciwysokoscudostępnionymi jako właściwości blokujące wartości ujemne, oraz metodęPole()zwracającą pole prostokąta.Zdefiniuj klasę
Uzytkownikz prywatnym polemhaslo, właściwościąHasloz walidacją wset(hasło musi mieć minimum 8 znaków — jeśli nie, nie przypisuj nowej wartości i wypisz komunikat błędu).Zbuduj klasę
KontoBankowerozbudowaną o historię transakcji: prywatną listęList<string>zapisującą tekstowy opis każdej wpłaty/wypłaty (z kwotą i datą), oraz publiczną metodęWyswietlHistorie()wypisującą wszystkie dotychczasowe operacje.
Typowe błędy
Częsty błąd to uczynienie WSZYSTKICH pól klasy public "dla wygody", co całkowicie eliminuje korzyści hermetyzacji — jeśli dane w ogóle mają być chronione, muszą być private z kontrolowanym dostępem przez właściwości/metody. Drugi błąd: właściwość z pustym, bezużytecznym set, który nic nie waliduje — wtedy równie dobrze pole mogłoby być public. Trzeci: próba dostępu do prywatnego pola z zewnątrz klasy, co zawsze kończy się błędem kompilacji ("inaccessibility level").
Nawiązanie do egzaminu zawodowego
To realizacja efektu INF.04.4.6 z podstawy programowej: "definiuje klasy" — konkretnie kryteria dotyczące pól, kwalifikatorów dostępu oraz metod, będące jednym z filarów programowania obiektowego w tej jednostce.