Konstruktory w C# – fabryka obiektów

Nauczysz się tworzyć konstruktory – specjalne metody odpowiedzialne za „budowanie” obiektów. Poznasz przeciążanie, słowo this i konstruktor kopiujący!

konstruktor new this przeciążanie kopiujący
01

Po co konstruktor?

Gdy tworzysz obiekt używając new, chcesz aby od razu miał sensowne wartości. Bez konstruktora musisz ręcznie ustawiać każde pole – to uciążliwe i łatwo o błąd.

cs/BezKonstruktora.cs C#
// 😰 Bez konstruktora – musisz ręcznie ustawić każde pole

public class Samochod
{
    public string Marka;
    public string Model;
    public int Rok;
    public double Przebieg;
}

// Tworzenie obiektu – pola mają domyślne wartości (null, 0)
Samochod auto = new Samochod();

// Musisz pamiętać o ustawieniu KAŻDEGO pola!
auto.Marka = "Toyota";
auto.Model = "Corolla";
auto.Rok = 2020;
auto.Przebieg = 45000;

// Co jeśli zapomnisz o jednym polu?
Samochod auto2 = new Samochod();
auto2.Marka = "Ford";
// Ups! Zapomniałem o Model, Rok, Przebieg...
// auto2.Model jest null – może spowodować błąd!
Problemy bez konstruktora
  • Można zapomnieć – łatwo pominąć jedno z pól
  • Pola mają domyślne wartości – string to null, int to 0 (nie zawsze sensowne)
  • Duplikacja kodu – za każdym razem te same 4 linie
  • Brak kontroli – nie można wymusić podania wartości

Konstruktor rozwiązuje te problemy – wymusza podanie wartości i inicjalizuje obiekt w jednym kroku.

02

Czym jest konstruktor?

Konstruktor to specjalna metoda wywoływana automatycznie w momencie tworzenia obiektu (new). Jej zadaniem jest przygotowanie obiektu do użycia – ustawienie początkowych wartości pól.

Analogia: Fabryka samochodów 🏭

Pomyśl o konstruktorze jak o linii montażowej w fabryce:

  • Konstruktor = linia montażowa
  • Parametry konstruktora = instrukcje montażu (jaki kolor, jaki silnik)
  • new = „uruchom linię produkcyjną”
  • Nowy obiekt = gotowy samochód zjeżdżający z taśmy

Gdy zamawiasz samochód, podajesz specyfikację (parametry), a fabryka (konstruktor) produkuje gotowy pojazd!

Analogia: Wypełnianie formularza 📝

Inna analogia:

  • Konstruktor bezparametrowy = formularz z domyślnymi wartościami
  • Konstruktor z parametrami = formularz, który MUSISZ wypełnić

Bank nie założy Ci konta bez podania danych – podobnie konstruktor może wymusić podanie wartości!

new Samochod(„Toyota”, „Corolla”)
Wywołanie
Konstruktor
Marka = „Toyota”
Model = „Corolla”
Rok = 2024
Gotowy obiekt! 🚗
W pamięci

Cechy konstruktora

CechaOpis
NazwaTaka sama jak nazwa klasy
Typ zwracanyBRAK! Nie piszemy void ani nic innego
WywołanieAutomatyczne przy new
ParametryMoże mieć dowolną liczbę (0, 1, 2, …)
PrzeciążanieMoże być wiele konstruktorów w klasie
03

Podstawowa składnia

Konstruktor definiujemy wewnątrz klasy. Jego nazwa musi być identyczna z nazwą klasy.

cs/SkladniaKonstruktora.cs C#
public class Samochod
{
    // Pola klasy
    public string Marka;
    public string Model;
    public int Rok;
    
    //     ↓ modyfikator    ↓ nazwa = nazwa klasy (BEZ typu zwracanego!)
    public Samochod()
    {
        // Kod wykonywany przy tworzeniu obiektu
        Marka = "Nieznana";
        Model = "Nieznany";
        Rok = 2024;
        
        Console.WriteLine("Konstruktor wywołany!");
    }
}

// Użycie – konstruktor wywoła się AUTOMATYCZNIE
Samochod auto = new Samochod();
// Wyświetli: "Konstruktor wywołany!"

Console.WriteLine(auto.Marka);  // "Nieznana"
Console.WriteLine(auto.Model);  // "Nieznany"
Console.WriteLine(auto.Rok);    // 2024

❌ To NIE jest konstruktor

// Ma typ zwracany void!
public void Samochod()
{
    // To zwykła metoda
    // o nazwie "Samochod"
}

✅ To JEST konstruktor

// Brak typu zwracanego!
public Samochod()
{
    // To konstruktor
    // wywoływany przy new
}
Najważniejsza różnica!

Konstruktor nie ma typu zwracanego – ani void, ani nic innego. Jeśli napiszesz public void Samochod(), to jest zwykła metoda, nie konstruktor!

04

Konstruktor domyślny (bezparametrowy)

Jeśli nie napiszesz żadnego konstruktora, C# automatycznie tworzy pusty konstruktor domyślny. Ale uwaga – gdy napiszesz własny konstruktor, domyślny znika!

Konstruktor domyślny – automatyczny

cs/KonstruktorDomyslny.cs C#
public class Osoba
{
    public string Imie;
    public int Wiek;
    
    // Nie napisaliśmy żadnego konstruktora
    // C# automatycznie dodaje pusty:
    // public Osoba() { }
}

// Działa! Używamy automatycznego konstruktora domyślnego
Osoba osoba = new Osoba();

// Pola mają domyślne wartości typów:
Console.WriteLine(osoba.Imie);  // null (domyślna dla string)
Console.WriteLine(osoba.Wiek);  // 0 (domyślna dla int)

⚠️ PUŁAPKA: Konstruktor domyślny znika!

cs/KonstruktorZnika.cs C#
public class Student
{
    public string Imie;
    public int Wiek;
    
    // Napisaliśmy konstruktor z parametrem
    public Student(string imie)
    {
        Imie = imie;
        Wiek = 18;
    }
    
    // UWAGA: Konstruktor domyślny ZNIKNĄŁ!
}

// To DZIAŁA – używamy naszego konstruktora
Student s1 = new Student("Jan");

// To NIE DZIAŁA – brak konstruktora bezparametrowego!
// Student s2 = new Student();  // ❌ BŁĄD KOMPILACJI!
// "There is no argument given that corresponds to the required
//  formal parameter 'imie'"
Zapamiętaj!

Gdy napiszesz jakikolwiek konstruktor z parametrami, konstruktor domyślny (bezparametrowy) automatycznie znika. Jeśli nadal go potrzebujesz, musisz go napisać ręcznie!

Rozwiązanie – dodaj oba konstruktory

cs/ObaKonstruktory.cs C#
public class Student
{
    public string Imie;
    public int Wiek;
    
    // Konstruktor bezparametrowy – ręcznie dodany
    public Student()
    {
        Imie = "Nieznane";
        Wiek = 0;
    }
    
    // Konstruktor z parametrem
    public Student(string imie)
    {
        Imie = imie;
        Wiek = 18;
    }
}

// Teraz OBA działają:
Student s1 = new Student();        // ✅ OK
Student s2 = new Student("Jan");  // ✅ OK
05

Konstruktor z parametrami

Konstruktor może przyjmować parametry – wartości przekazywane przy tworzeniu obiektu. Pozwala to na inicjalizację pól konkretnymi danymi.

Jeden parametr

cs/JedenParametr.cs C#
public class Ksiazka
{
    public string Tytul;
    public string Autor;
    public int Strony;
    
    public Ksiazka(string tytul)
    {
        Tytul = tytul;
        Autor = "Nieznany";   // Wartość domyślna
        Strony = 0;            // Wartość domyślna
    }
}

// Użycie – MUSISZ podać tytuł
Ksiazka k = new Ksiazka("Hobbit");
Console.WriteLine(k.Tytul);  // "Hobbit"
Console.WriteLine(k.Autor);  // "Nieznany"

Wiele parametrów

cs/WieleParametrow.cs C#
public class Prostokat
{
    public double Szerokosc;
    public double Wysokosc;
    public string Kolor;
    
    public Prostokat(double szerokosc, double wysokosc, string kolor)
    {
        Szerokosc = szerokosc;
        Wysokosc = wysokosc;
        Kolor = kolor;
    }
    
    public double ObliczPole()
    {
        return Szerokosc * Wysokosc;
    }
}

// Użycie – parametry w ODPOWIEDNIEJ KOLEJNOŚCI!
Prostokat p = new Prostokat(10.5, 7.2, "czerwony");

Console.WriteLine($"Prostokąt {p.Kolor}: {p.Szerokosc} x {p.Wysokosc}");
Console.WriteLine($"Pole: {p.ObliczPole()}");
Kolejność parametrów ma znaczenie!

Parametry są przekazywane w kolejności zdefiniowanej w konstruktorze:

new Prostokat(10.5, 7.2, "czerwony");
              ↓     ↓        ↓
         szerokosc wysokosc kolor

Jeśli pomylisz kolejność, program może działać niepoprawnie!

06

Przeciążanie konstruktorów

Przeciążanie (overloading) oznacza, że klasa może mieć wiele konstruktorów z różnymi parametrami. C# wybiera odpowiedni konstruktor na podstawie przekazanych argumentów.

cs/Przeciazanie.cs C#
public class Telefon
{
    public string Marka;
    public string Model;
    public decimal Cena;
    
    // Konstruktor 1 – bez parametrów
    public Telefon()
    {
        Marka = "Nieznana";
        Model = "Nieznany";
        Cena = 0;
    }
    
    // Konstruktor 2 – tylko marka
    public Telefon(string marka)
    {
        Marka = marka;
        Model = "Nieznany";
        Cena = 0;
    }
    
    // Konstruktor 3 – marka i model
    public Telefon(string marka, string model)
    {
        Marka = marka;
        Model = model;
        Cena = 0;
    }
    
    // Konstruktor 4 – wszystkie parametry
    public Telefon(string marka, string model, decimal cena)
    {
        Marka = marka;
        Model = model;
        Cena = cena;
    }
}
cs/UzyciePrzeciazania.cs C#
// C# automatycznie wybiera odpowiedni konstruktor!

Telefon t1 = new Telefon();                             // → Konstruktor 1
Telefon t2 = new Telefon("Samsung");                     // → Konstruktor 2
Telefon t3 = new Telefon("Apple", "iPhone 15");         // → Konstruktor 3
Telefon t4 = new Telefon("Xiaomi", "Mi 13", 1200.50m); // → Konstruktor 4

Console.WriteLine($"{t1.Marka}");  // "Nieznana"
Console.WriteLine($"{t2.Marka}");  // "Samsung"
Console.WriteLine($"{t3.Model}");  // "iPhone 15"
Console.WriteLine($"{t4.Cena:C}"); // "1 200,50 zł"
new Telefon()
0 argumentów
Konstruktor 1
Bezparametrowy
new Telefon(„Samsung”)
1 string
Konstruktor 2
string marka
new Telefon(„Apple”, „iPhone”)
2 stringi
Konstruktor 3
string, string
Jak C# wybiera konstruktor?

Na podstawie liczby i typów przekazanych argumentów:

  • 0 argumentów → szuka konstruktora bez parametrów
  • 1 string → szuka konstruktora z jednym string
  • 2 stringi → szuka konstruktora z dwoma string
07

Słowo kluczowe this

this to odwołanie do bieżącego obiektu. Używamy go głównie gdy nazwa parametru jest taka sama jak nazwa pola – this rozróżnia je.

Problem: Takie same nazwy

cs/ProblemNazw.cs C#
public class Auto
{
    public string marka;   // Pole klasy
    public string model;   // Pole klasy
    
    // ❌ PROBLEM: parametry mają te same nazwy co pola!
    public Auto(string marka, string model)
    {
        marka = marka;  // 🤔 Które "marka"? Parametr = parametr!
        model = model;  // To nic nie robi – przypisuje parametr do siebie
    }
}

Auto a = new Auto("Toyota", "Corolla");
Console.WriteLine(a.marka);  // null! Pole nie zostało ustawione!

Rozwiązanie: this

cs/RozwiazanieThis.cs C#
public class Auto
{
    public string marka;
    public string model;
    
    public Auto(string marka, string model)
    {
        this.marka = marka;  // this.marka = POLE, marka = PARAMETR
        this.model = model;  // this.model = POLE, model = PARAMETR
    }
}

Auto a = new Auto("Toyota", "Corolla");
Console.WriteLine(a.marka);  // "Toyota" ✅
this.marka
POLE klasy
(w obiekcie)
=
marka
PARAMETR
(przekazany)
Alternatywa: Różne nazwy

Możesz też użyć innych nazw parametrów – wtedy this nie jest potrzebne:

public Auto(string nowaMarka, string nowyModel)
{
    marka = nowaMarka;  // OK – nazwy są różne
    model = nowyModel;
}

Ale konwencja z this jest popularna i czytelna.

08

Wywoływanie innych konstruktorów – this(…)

Konstruktor może wywoływać inny konstruktor tej samej klasy używając : this(...). Pozwala to uniknąć duplikacji kodu.

cs/BezThis.cs C#
// 😰 PROBLEM: Duplikacja kodu w konstruktorach

public class Punkt
{
    public int X;
    public int Y;
    public string Kolor;
    
    public Punkt()
    {
        X = 0;
        Y = 0;
        Kolor = "Czarny";
    }
    
    public Punkt(int x, int y)
    {
        X = x;
        Y = y;
        Kolor = "Czarny";  // Powtórzenie!
    }
    
    public Punkt(int x, int y, string kolor)
    {
        X = x;               // Powtórzenie!
        Y = y;               // Powtórzenie!
        Kolor = kolor;
    }
}
cs/ZThis.cs C#
// 😊 ROZWIĄZANIE: Konstruktory wywołują się nawzajem

public class Punkt
{
    public int X;
    public int Y;
    public string Kolor;
    
    // Konstruktor "główny" – pełna logika
    public Punkt(int x, int y, string kolor)
    {
        X = x;
        Y = y;
        Kolor = kolor;
    }
    
    // Wywołuje konstruktor główny z domyślnym kolorem
    public Punkt(int x, int y) : this(x, y, "Czarny")
    {
        // Dodatkowy kod (opcjonalny)
    }
    
    // Wywołuje konstruktor z domyślnymi współrzędnymi
    public Punkt() : this(0, 0, "Czarny")
    {
        // Dodatkowy kod (opcjonalny)
    }
}
new Punkt()
Wywołanie
this(0, 0, „Czarny”)
Przekierowanie
Punkt(int, int, string)
Główny konstruktor
Zasada DRY (Don’t Repeat Yourself)

Dzięki this(...) logika inicjalizacji jest w jednym miejscu. Jeśli coś zmienisz, zmieniasz tylko konstruktor główny!

09

Konstruktor kopiujący

Konstruktor kopiujący tworzy nowy obiekt na podstawie istniejącego. W C# nie ma go automatycznie – musisz napisać go sam.

Problem: Kopiowanie referencji

cs/ProblemKopiowania.cs C#
public class Osoba
{
    public string Imie;
    public int Wiek;
    
    public Osoba(string imie, int wiek)
    {
        Imie = imie;
        Wiek = wiek;
    }
}

// Tworzę obiekt
Osoba osoba1 = new Osoba("Jan", 25);

// ❌ TO NIE TWORZY KOPII!
Osoba osoba2 = osoba1;  // Tylko kopia REFERENCJI!

// Zmiana w osoba2 zmienia też osoba1!
osoba2.Wiek = 30;

Console.WriteLine(osoba1.Wiek);  // 30! 😱 To ten sam obiekt!
Console.WriteLine(osoba2.Wiek);  // 30
osoba1
referencja
Obiekt w pamięci
Imie: „Jan”
Wiek: 30
osoba2
ta sama referencja!

Rozwiązanie: Konstruktor kopiujący

cs/KonstruktorKopiujacy.cs C#
public class Osoba
{
    public string Imie;
    public int Wiek;
    
    // Konstruktor normalny
    public Osoba(string imie, int wiek)
    {
        Imie = imie;
        Wiek = wiek;
    }
    
    // KONSTRUKTOR KOPIUJĄCY – parametr to obiekt tego samego typu
    public Osoba(Osoba inna)
    {
        if (inna != null)
        {
            this.Imie = inna.Imie;
            this.Wiek = inna.Wiek;
        }
    }
}

// Tworzę obiekt
Osoba osoba1 = new Osoba("Jan", 25);

// ✅ Tworzę PRAWDZIWĄ KOPIĘ
Osoba osoba2 = new Osoba(osoba1);  // Konstruktor kopiujący!

// Teraz to są RÓŻNE obiekty
osoba2.Wiek = 30;

Console.WriteLine(osoba1.Wiek);  // 25 ✅ Nie zmieniło się!
Console.WriteLine(osoba2.Wiek);  // 30

Kopiowanie zagnieżdżonych obiektów

cs/KopiaGleboka.cs C#
public class Adres
{
    public string Miasto;
    public string Ulica;
    
    public Adres(string miasto, string ulica)
    {
        Miasto = miasto;
        Ulica = ulica;
    }
    
    public Adres(Adres inny)  // Konstruktor kopiujący dla Adres
    {
        if (inny != null)
        {
            Miasto = inny.Miasto;
            Ulica = inny.Ulica;
        }
    }
}

public class Pracownik
{
    public string Imie;
    public Adres AdresZamieszkania;  // Zagnieżdżony obiekt!
    
    public Pracownik(string imie, Adres adres)
    {
        Imie = imie;
        AdresZamieszkania = adres;
    }
    
    public Pracownik(Pracownik inny)
    {
        if (inny != null)
        {
            Imie = inny.Imie;
            
            // WAŻNE! Tworzymy KOPIĘ adresu, nie kopiujemy referencji!
            if (inny.AdresZamieszkania != null)
            {
                AdresZamieszkania = new Adres(inny.AdresZamieszkania);
            }
        }
    }
}
Kopia płytka vs głęboka
  • Kopia płytka – kopiujesz pola proste, ale referencje wskazują na te same obiekty
  • Kopia głęboka – tworzysz też kopie zagnieżdżonych obiektów (jak powyżej)

Dla obiektów zawierających inne obiekty, zawsze twórz kopię głęboką!

10

Walidacja w konstruktorze

Konstruktor to idealne miejsce na walidację danych. Możesz sprawdzić, czy przekazane wartości są poprawne i zareagować na błędy.

cs/Walidacja.cs C#
public class Student
{
    public string Imie;
    public int Wiek;
    public double Srednia;
    
    public Student(string imie, int wiek, double srednia)
    {
        // Walidacja imienia
        if (string.IsNullOrWhiteSpace(imie))
        {
            throw new ArgumentException("Imię nie może być puste!");
        }
        
        // Walidacja wieku
        if (wiek < 16 || wiek > 100)
        {
            throw new ArgumentOutOfRangeException("Wiek musi być między 16 a 100!");
        }
        
        // Walidacja średniej
        if (srednia < 1.0 || srednia > 6.0)
        {
            throw new ArgumentOutOfRangeException("Średnia musi być między 1.0 a 6.0!");
        }
        
        // Wszystko OK – przypisujemy wartości
        Imie = imie;
        Wiek = wiek;
        Srednia = srednia;
    }
}

// Użycie:
try
{
    Student s1 = new Student("Jan", 20, 4.5);  // ✅ OK
    Student s2 = new Student("", 20, 4.5);     // ❌ Wyjątek!
    Student s3 = new Student("Anna", 150, 4.0); // ❌ Wyjątek!
}
catch (Exception ex)
{
    Console.WriteLine($"Błąd: {ex.Message}");
}
Walidacja z wartościami domyślnymi

Zamiast rzucać wyjątek, możesz ustawić wartość domyślną:

if (wiek < 0) 
{
    wiek = 0;  // Napraw zamiast rzucać wyjątek
}
Wiek = wiek;

Zależy od wymagań – czasem błąd powinien być widoczny!

11

Praktyczne przykłady

Przykład 1: Konto bankowe

cs/KontoBankowe.cs C#
public class KontoBankowe
{
    public string NumerKonta;
    public string Wlasciciel;
    public decimal Saldo;
    
    // Nowe konto – zawsze zaczyna od 0 zł
    public KontoBankowe(string numer, string wlasciciel)
    {
        NumerKonta = numer;
        Wlasciciel = wlasciciel;
        Saldo = 0;
    }
    
    // Konto z początkowym saldem (np. przelew z innego banku)
    public KontoBankowe(string numer, string wlasciciel, decimal saldo) 
        : this(numer, wlasciciel)
    {
        if (saldo >= 0)
        {
            Saldo = saldo;
        }
    }
    
    public void WyswietlInfo()
    {
        Console.WriteLine($"Konto: {NumerKonta}");
        Console.WriteLine($"Właściciel: {Wlasciciel}");
        Console.WriteLine($"Saldo: {Saldo:C}");
    }
}

Przykład 2: Uczeń z wieloma konstruktorami

cs/Uczen.cs C#
public class Uczen
{
    public string Imie;
    public string Nazwisko;
    public string Klasa;
    public double Srednia;
    
    // Konstruktor główny
    public Uczen(string imie, string nazwisko, string klasa, double srednia)
    {
        Imie = imie;
        Nazwisko = nazwisko;
        Klasa = klasa;
        Srednia = srednia;
    }
    
    // Nowy uczeń – jeszcze bez ocen
    public Uczen(string imie, string nazwisko, string klasa) 
        : this(imie, nazwisko, klasa, 0.0)
    {
    }
    
    // Konstruktor kopiujący
    public Uczen(Uczen inny) 
        : this(inny.Imie, inny.Nazwisko, inny.Klasa, inny.Srednia)
    {
    }
    
    public string PelneImie() => $"{Imie} {Nazwisko}";
}
12

Częste błędy

❌ Błąd 1: Typ zwracany w konstruktorze

❌ Źle

public void Samochod()
{
    // To NIE jest konstruktor!
    // To zwykła metoda void
}

✅ Dobrze

public Samochod()
{
    // To JEST konstruktor
    // Brak typu zwracanego!
}

❌ Błąd 2: Inna nazwa niż klasa

❌ Źle

public class Auto
{
    public Samochod()  // Zła nazwa!
    {
    }
}

✅ Dobrze

public class Auto
{
    public Auto()  // Taka sama nazwa!
    {
    }
}

❌ Błąd 3: Brak konstruktora bezparametrowego

❌ Źle

public class Osoba
{
    public Osoba(string imie) { }
}

// Nie działa!
Osoba o = new Osoba();

✅ Dobrze

public class Osoba
{
    public Osoba() { }  // Dodaj!
    public Osoba(string imie) { }
}

// Teraz działa
Osoba o = new Osoba();

❌ Błąd 4: Brak this przy tych samych nazwach

❌ Źle

public class Auto
{
    public string marka;
    
    public Auto(string marka)
    {
        marka = marka;  // Nic nie robi!
    }
}

✅ Dobrze

public class Auto
{
    public string marka;
    
    public Auto(string marka)
    {
        this.marka = marka;  // OK!
    }
}

❌ Błąd 5: Płytka kopia zamiast głębokiej

❌ Źle

public Pracownik(Pracownik inny)
{
    Imie = inny.Imie;
    // Kopia referencji!
    Adres = inny.Adres;
}

✅ Dobrze

public Pracownik(Pracownik inny)
{
    Imie = inny.Imie;
    // Kopia obiektu!
    Adres = new Adres(inny.Adres);
}
13

Podsumowanie

Kluczowe pojęcia
  • Konstruktor – specjalna metoda wywoływana przy new
  • Nazwa – identyczna z nazwą klasy
  • Brak typu zwracanego – nie piszemy void ani nic innego
  • Konstruktor domyślny – znika gdy napiszesz własny!
  • Przeciążanie – wiele konstruktorów z różnymi parametrami
  • this – odwołanie do bieżącego obiektu
  • this(...) – wywołanie innego konstruktora
  • Konstruktor kopiujący – tworzy kopię obiektu

Rodzaje konstruktorów

RodzajOpisPrzykład
DomyślnyBez parametrów, automatyczny lub ręcznypublic Klasa()
Z parametramiPrzyjmuje wartości początkowepublic Klasa(string s)
KopiującyTworzy kopię istniejącego obiektupublic Klasa(Klasa inna)

Schemat składni

cs/Schemat.cs C#
public class NazwaKlasy
{
    public typ Pole;
    
    // Konstruktor bezparametrowy
    public NazwaKlasy()
    {
        Pole = wartoscDomyslna;
    }
    
    // Konstruktor z parametrami
    public NazwaKlasy(typ parametr)
    {
        this.Pole = parametr;
    }
    
    // Konstruktor wywołujący inny
    public NazwaKlasy(typ a, typ b) : this(a)
    {
        // Dodatkowy kod
    }
    
    // Konstruktor kopiujący
    public NazwaKlasy(NazwaKlasy inny)
    {
        this.Pole = inny.Pole;
    }
}
Zadania

Zadania praktyczne

📝 Zadanie 1: Klasa Film

Utwórz klasę Film z polami: Tytul, Rezyser, RokProdukcji, CzasTrwania (w minutach).

Dodaj konstruktory:

  • Bezparametrowy (domyślne wartości)
  • Z tytułem i reżyserem
  • Z wszystkimi parametrami

Utwórz 3 filmy używając różnych konstruktorów.

💡 Podpowiedź: Użyj this(...) aby uniknąć duplikacji

📝 Zadanie 2: Klasa Komputer

Utwórz klasę Komputer z polami: Procesor, Ram (GB), Dysk (GB), Cena.

Dodaj:

  • Konstruktor pełny
  • Konstruktor "budżetowy" (tylko procesor, Ram=8, Dysk=256)
  • Konstruktor kopiujący

💡 Podpowiedź: Konstruktor budżetowy może wywoływać pełny z this(...)

📝 Zadanie 3: Znajdź błędy

Popraw poniższy kod:

cs/Bledy.cs C#
public class Zwierze
{
    public string Gatunek;
    public int Wiek;
    
    public int Zwierze(string gatunek)
    {
        Gatunek = gatunek;
        return 0;
    }
}

💡 Podpowiedź: Jest tu kilka błędów związanych z konstruktorem

⭐ Zadanie 4: Walidacja w konstruktorze

Utwórz klasę Produkt z polami: Nazwa, Cena, Ilosc.

Dodaj walidację w konstruktorze:

  • Nazwa nie może być pusta
  • Cena musi być większa od 0
  • Ilość nie może być ujemna

Rzuć odpowiedni wyjątek przy błędnych danych.

💡 Podpowiedź: Użyj ArgumentException i ArgumentOutOfRangeException

⭐⭐ Zadanie 5: System zamówień

Utwórz klasy:

  • Adres: Miasto, Ulica, KodPocztowy + konstruktor kopiujący
  • Klient: Imie, Email, Adres (obiekt!) + konstruktor kopiujący (głęboka kopia!)
  • Zamowienie: Numer, Klient, DataZlozenia, Wartosc

Każda klasa powinna mieć konstruktor pełny i kopiujący. Zamówienie przy tworzeniu automatycznie ustawia DataZlozenia na DateTime.Now.

💡 Podpowiedź: Pamiętaj o głębokiej kopii zagnieżdżonych obiektów!