Nauka techniki hermetyzacji (enkapsulacji) danych poprzez ukrywanie pól klasy i udostępnianie ich za pomocą właściwości (properties). Student dowie się, jak walidować dane wejściowe, korzystać z akcesorów get/set oraz tworzyć pola tylko do odczytu.
Po incydentach z błędnymi danymi w komisie "Auto-Premium", decydujesz się na wprowadzenie rygorystycznych zasad. System nie może już przyjmować ujemnych lat produkcji ani pustych nazw marek. Jako główny architekt rozwiązujesz ten problem, zmieniając wszystkie publiczne pola klasy "Samochod" na prywatne. Zewnętrzny świat nie ma już do nich bezpośredniego dostępu.
W zamian wprowadzasz "strażników danych" – publiczne właściwości. Każda próba ustawienia nowej wartości przechodzi przez blok sprawdzający (set), który weryfikuje sensowność danych (np. rok produkcji nie może być starszy niż pierwszy samochód Benza z 1885 roku). Dodatkowo wprowadzasz pole identyfikacyjne, które raz nadane, nigdy nie powinno ulec zmianie. Dzięki tym zabiegom, Twój system staje się odporny na błędy ludzkie i gwarantuje, że stan każdego obiektu jest zawsze poprawny i spójny.
using System;
namespace LaboratoriumOOP
{
public class Samochod
{
// POLE PRYWATNE: Ukryte przed światem zewnętrznym.
// Konwencja: _nazwa (camelCase z podkreśleniem).
private string _marka;
private int _rokProdukcji;
// POLE TYLKO DO ODCZYTU: Można je ustawić tylko raz.
public readonly string NumerSeryjny = "VIN-TEMP-2024";
// WŁAŚCIWOŚĆ (Property): Publiczny interfejs dostępu do pola prywatnego.
public string Marka
{
get { return _marka; }
set
{
// Walidacja: value to niejawny parametr przekazywany do settera.
if (string.IsNullOrWhiteSpace(value))
{
Console.WriteLine($"OSTRZEŻENIE: Próba wpisania pustej marki dla {nameof(Marka)}.");
_marka = "Nieznana";
}
else
{
_marka = value;
}
}
}
public string Model { get; set; } // Właściwość automatyczna (skrócony zapis)
public int RokProdukcji
{
get { return _rokProdukcji; }
set
{
// Zaawansowana walidacja
int obecnyRok = DateTime.Now.Year;
if (value < 1885 || value > obecnyRok)
{
Console.WriteLine($"BŁĄD: Rok {value} jest poza zakresem (1885-{obecnyRok}). Ustawiam rok domyślny.");
_rokProdukcji = obecnyRok;
}
else
{
_rokProdukcji = value;
}
}
}
// WŁAŚCIWOŚĆ WYLICZANA: Tylko do odczytu (brak bloku set).
public int WiekSamochodu
{
get { return DateTime.Now.Year - _rokProdukcji; }
}
public void WyswietlInformacje()
{
Console.WriteLine($"[{NumerSeryjny}] {Marka} {Model}, Rok: {RokProdukcji} (Wiek: {WiekSamochodu} lat)");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("--- ZADANIE 02: Hermetyzacja i ochrona stanu ---\n");
Samochod auto1 = new Samochod();
// Korzystamy z właściwości zamiast pól
auto1.Marka = "Audi";
auto1.Model = "A4";
auto1.RokProdukcji = 2018;
Console.WriteLine("1. Prawidłowe dane:");
auto1.WyswietlInformacje();
Console.WriteLine("\n2. Próba wprowadzenia błędnych danych:");
Samochod auto2 = new Samochod();
auto2.Marka = " "; // Próba wpisania pustego ciągu
auto2.RokProdukcji = 1410; // Próba wpisania daty bitwy pod Grunwaldem
Console.WriteLine("\nStan obiektu po walidacji:");
auto2.WyswietlInformacje();
// Próba zmiany pola readonly (odkomentowanie wywoła błąd kompilacji)
// auto1.NumerSeryjny = "NOWY-VIN";
Console.WriteLine("\nPodsumowanie: Dzięki hermetyzacji obiekt sam dba o swoją poprawność.");
Console.WriteLine("Naciśnij dowolny klawisz, aby zakończyć...");
Console.ReadKey();
}
}
}