Nauka tworzenia hierarchii klas przy użyciu dziedziczenia oraz zrozumienie roli modyfikatora dostępu protected. Student dowie się, jak wywoływać konstruktor bazowy, używać składowych statycznych oraz jak korzystać z przestrzeni nazw.
Firma "Auto-Premium" dynamicznie się rozwija i wprowadza do oferty nie tylko samochody, ale również motocykle. Zauważasz, że oba te typy pojazdów mają wiele wspólnych cech, takich jak marka czy rok produkcji, ale różnią się też unikalnymi parametrami – samochody mają liczbę drzwi, a motocykle mogą posiadać wózek boczny. To idealny moment na wprowadzenie techniki dziedziczenia, aby nie powielać kodu i zachować porządek w systemie.
Projektujesz ogólną klasę bazową Pojazd, która staje się fundamentem dla bardziej wyspecjalizowanych klas Samochod i Motocykl. Wykorzystujesz modyfikator protected, aby Twoje "dzieci" (klasy pochodne) miały swobodny dostęp do kluczowych pól rodzica, jednocześnie chroniąc te dane przed dostępem z zewnątrz (np. bezpośrednio z poziomu metody Main). Aby mieć pełny wgląd w skalę biznesu, wprowadzasz statyczny licznik, który automatycznie zlicza każdy nowy pojazd trafiający do bazy. Dzięki strukturze przestrzeni nazw (namespaces), Twój kod staje się profesjonalnie zorganizowany i gotowy na dalszą rozbudowę.
LaboratoriumOOP.Modele i umieść w niej klasy pojazdów.Pojazd z polami protected string Marka oraz protected int Rok.Samochod (dziedziczącą po Pojazd) z unikalnym polem LiczbaDrzwi.Motocykl z polem bool CzyMaWozek.base(marka, rok), aby przekazać dane do konstruktora rodzica.LicznikPojazdow w klasie Pojazd, które zwiększa się przy każdej nowej instancji.WyswietlStanKomisu(), która wypisze aktualną liczbę wszystkich pojazdów.Main utwórz listę typu List<Pojazd> i dodaj do niej zarówno samochody, jak i motocykle (demonstracja rzutowania w górę - upcasting).Marka (protected) z poziomu Main kończy się błędem kompilacji.
using System;
using System.Collections.Generic;
// Używamy własnej przestrzeni nazw
using LaboratoriumOOP.Modele;
namespace LaboratoriumOOP.Modele
{
// KLASA BAZOWA: Fundament hierarchii
public class Pojazd
{
// protected: widoczne tylko w tej klasie i klasach pochodnych
protected string Marka;
protected int Rok;
// static: pole współdzielone przez wszystkie instancje (licznik globalny)
public static int LicznikPojazdow = 0;
public Pojazd(string marka, int rok)
{
Marka = marka;
Rok = rok;
LicznikPojazdow++;
Console.WriteLine($"[INFO] Dodano nowy pojazd do bazy: {marka}.");
}
public static void WyswietlStanKomisu()
{
Console.WriteLine($"\n--- STAN KOMISU: {LicznikPojazdow} pojazdów ---");
}
public virtual void WyswietlInfo()
{
Console.Write($"Pojazd: {Marka} ({Rok})");
}
}
// DZIEDZICZENIE: Samochod "jest" (IS-A) Pojazdem
public class Samochod : Pojazd
{
public int LiczbaDrzwi { get; set; }
// base: wywołanie konstruktora klasy bazowej
public Samochod(string marka, int rok, int drzwi) : base(marka, rok)
{
LiczbaDrzwi = drzwi;
}
public override void WyswietlInfo()
{
base.WyswietlInfo();
Console.WriteLine($" [Samochod, Drzwi: {LiczbaDrzwi}]");
}
}
// SEALED: zapobiega dalszemu dziedziczeniu po tej klasie
public sealed class Motocykl : Pojazd
{
public bool CzyMaWozek { get; set; }
public Motocykl(string marka, int rok, bool wozek) : base(marka, rok)
{
CzyMaWozek = wozek;
}
public override void WyswietlInfo()
{
base.WyswietlInfo();
string wozekInfo = CzyMaWozek ? "Tak" : "Nie";
Console.WriteLine($" [Motocykl, Wozek boczny: {wozekInfo}]");
}
}
}
namespace LaboratoriumOOP
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("--- ZADANIE 05: Dziedziczenie i statyczne elementy ---\n");
// UPCASTING: Możemy przechowywać różne pojazdy w jednej liście typu Pojazd
List flota = new List();
flota.Add(new Samochod("Volvo", 2020, 5));
flota.Add(new Motocykl("Yamaha", 2022, false));
flota.Add(new Samochod("Tesla", 2024, 4));
// Próba dostępu:
// Console.WriteLine(flota[0].Marka); // BŁĄD KOMPILACJI - Marka jest protected!
Console.WriteLine("\nZawartość floty:");
foreach (var p in flota)
{
p.WyswietlInfo(); // Polimorficzne wywołanie metody
}
// Dostęp do metody statycznej przez nazwę klasy, nie przez obiekt
Pojazd.WyswietlStanKomisu();
Console.WriteLine("\nZakończono. Naciśnij klawisz...");
Console.ReadKey();
}
}
}