Lekcja 12. Konstruktory (zwykły i kopiujący) i destruktor
Trudny / egzaminacyjnyPo co się tego uczymy?
Bez konstruktora tworzenie w pełni wypełnionego obiektu wymaga kilku osobnych linii kodu za każdym razem, co jest niewygodne i łatwo o pomyłkę (np. zapomnienie ustawienia jednego pola). Konstruktor gwarantuje, że obiekt od razu "rodzi się" w poprawnym, kompletnym stanie.
Teoria
W Lekcjach 9-10 tworzyłeś obiekt przez new Film(), a potem RĘCZNIE przypisywałeś wartości polom w kolejnych liniach. Konstruktor pozwala zrobić to od razu, w jednym kroku, w momencie tworzenia obiektu.
Konstruktor to specjalna metoda o TAKIEJ SAMEJ nazwie jak klasa, bez typu zwracanego, wywoływana automatycznie przy każdym new:
public Film(string tytul, int rok, double cena) { Tytul = tytul; Rok = rok; Cena = cena; }
Użycie: Film film1 = new Film("Diuna", 2021, 12.99); — obiekt jest od razu w pełni wypełniony.
Konstruktory można PRZECIĄŻAĆ (dokładnie jak zwykłe metody, Lekcja 7) — klasa może mieć kilka konstruktorów o różnej liczbie parametrów, np. jeden przyjmujący wszystkie dane, drugi ustawiający tylko część, a resztę na wartości domyślne.
Konstruktor kopiujący tworzy nowy obiekt jako KOPIĘ istniejącego, przyjmując jako parametr obiekt tej samej klasy i przepisując z niego wartości pól:
public Film(Film inny) { Tytul = inny.Tytul; Rok = inny.Rok; Cena = inny.Cena; }
Użycie: Film kopia = new Film(film1); — kopia ma te same wartości co film1, ale jest CAŁKOWICIE NIEZALEŻNYM obiektem (zmiana pola w kopii nie wpływa na oryginał).
Destruktor to metoda wywoływana, gdy obiekt jest usuwany z pamięci przez tzw. Garbage Collector (.NET sam automatycznie zarządza pamięcią, w przeciwieństwie do C++) — w C# destruktory są rzadko potrzebne w praktyce, ale warto wiedzieć, że istnieją, do zwalniania rzadkich, specjalnych zasobów: ~Film() { ... }
Przykład z życia
Zamawiając samochód u dealera, od razu podajesz wszystkie parametry (kolor, silnik, wyposażenie) — samochód nie "powstaje" najpierw pusty, żeby dopiero potem ktoś ręcznie dokładał mu kolor i silnik. To dokładnie rola konstruktora.
Kod (C#)
using System;
class Film
{
public string Tytul;
public int Rok;
public double Cena;
// konstruktor - wypełnia obiekt od razu przy tworzeniu
public Film(string tytul, int rok, double cena)
{
Tytul = tytul;
Rok = rok;
Cena = cena;
}
// konstruktor kopiujący - tworzy NIEZALEŻNĄ kopię innego filmu
public Film(Film inny)
{
Tytul = inny.Tytul;
Rok = inny.Rok;
Cena = inny.Cena;
}
public void WyswietlInfo()
{
Console.WriteLine(Tytul + " (" + Rok + ") - " + Cena + " zł");
}
}
class Program
{
static void Main()
{
Film film1 = new Film("Diuna: Część Trzecia", 2026, 12.99);
film1.WyswietlInfo();
Film kopia = new Film(film1); // konstruktor kopiujący
kopia.Cena = 9.99; // zmiana kopii NIE wpływa na film1
Console.WriteLine("Oryginał: ");
film1.WyswietlInfo();
Console.WriteLine("Kopia (z inną ceną): ");
kopia.WyswietlInfo();
}
}
Komentarz i wyjaśnienie kodu
Zwróć uwagę, że oba konstruktory mają TĘ SAMĄ nazwę (Film) — C# rozróżnia je po parametrach, dokładnie jak przy przeciążaniu zwykłych metod (Lekcja 7). Kluczowe w konstruktorze kopiującym jest to, że kopia i film1 to DWA OSOBNE obiekty w pamięci — zmiana kopia.Cena w żaden sposób nie zmienia film1.Cena, mimo że na starcie miały identyczne wartości.
Ćwiczenie samodzielne
Dodaj do klasy Osoba (z Lekcji 10) konstruktor przyjmujący imię i wiek, i użyj go do utworzenia trzech obiektów w jednej linii każdy.
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
Dodaj konstruktor do klasy
Prostokatz Lekcji 11, przyjmujący szerokość i wysokość jako parametry.Zdefiniuj klasę
Produktz konstruktorem przyjmującym nazwę i cenę, oraz DRUGIM, przeciążonym konstruktorem bez parametrów, ustawiającym domyślną nazwę "Nieznany produkt" i cenę 0.Zdefiniuj klasę
Pracownikz pełnym konstruktorem (imię, stanowisko, pensja) oraz konstruktorem kopiującym. Utwórz pracownika, następnie jego kopię z podwyższoną pensją (symulacja awansu) — tak, żeby oryginalny obiekt pozostał niezmieniony, a program wypisał dane obu wersji do porównania.
Typowe błędy
Częsty błąd to nadanie konstruktorowi innej nazwy niż nazwa klasy — C# rozpozna to wtedy jako zwykłą metodę, a nie konstruktor, i nie będzie wywoływana automatycznie przy new. Drugi błąd: dodanie konstruktorowi typu zwracanego (np. void) — konstruktory NIGDY nie mają typu zwracanego, nawet void. Trzeci: przekonanie, że przypisanie Film kopia = film1; (bez new i konstruktora kopiującego) tworzy niezależną kopię — w rzeczywistości kopia wskazywałaby na TEN SAM obiekt co film1, więc zmiana jednego zmieniłaby też drugi.
Nawiązanie do egzaminu zawodowego
To realizacja efektu INF.04.4.6 z podstawy programowej: "definiuje klasy" — konkretnie kryterium dotyczące konstruktorów, w tym KONSTRUKTORA KOPIUJĄCEGO wymienionego wprost w oficjalnym tekście podstawy, oraz destruktora.