Menu
Coddy logo textTech

Rzutowanie w górę i w dół

Część sekcji Programowanie obiektowe ścieżki C# w Coddy. Lekcja 29 z 70.

Podczas pracy z hierarchiami dziedziczenia często trzeba konwertować typy bazowe na pochodne i odwrotnie. Rzutowanie w górę konwertuje typ pochodny na bazowy, a rzutowanie w dół robi odwrotnie.

Rzutowanie w górę jest niejawne i zawsze bezpieczne, ponieważ klasa pochodna na pewno ma wszystko, co ma klasa bazowa:

Dog myDog = new Dog();
Animal animal = myDog;  // Rzutowanie w górę – niejawne, zawsze działa

Rzutowanie w dół wymaga jawnego rzutowania i może zakończyć się niepowodzeniem w czasie wykonywania, jeśli obiekt w rzeczywistości nie jest typu, na który go rzutujesz:

Animal animal = new Dog();
Dog dog = (Dog)animal;  // Rzutowanie w dół – działa, ponieważ obiekt jest w rzeczywistości typu Dog

Animal cat = new Cat();
Dog wrong = (Dog)cat;   // Zgłasza InvalidCastException!

Aby bezpiecznie rzutować w dół, najpierw użyj słowa kluczowego is, aby sprawdzić typ, albo użyj as, które zwraca null zamiast zgłaszać wyjątek:

if (animal is Dog d)
{
    d.Bark();  // Bezpieczne — d jest dostępne tylko wtedy, gdy sprawdzenie się powiedzie
}

Dog maybeDog = animal as Dog;
if (maybeDog != null)
{
    maybeDog.Bark();
}

We współczesnym C# preferowane jest podejście z dopasowaniem wzorca is, ponieważ łączy sprawdzenie typu i rzutowanie w jednym kroku, dzięki czemu Twój kod jest bezpieczniejszy i bardziej przejrzysty.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system kontroli pojazdów, który pokazuje, jak rzutowanie w górę i rzutowanie w dół pozwalają elastycznie pracować z obiektami w hierarchii dziedziczenia. Utworzysz różne typy pojazdów i napiszesz kod, który bezpiecznie rozpoznaje konkretne rodzaje pojazdów i wchodzi z nimi w interakcję.

Rozmieścisz kod w czterech plikach:

  • Vehicle.cs: Zdefiniuj bazową klasę Vehicle w przestrzeni nazw Inspection. Każdy pojazd ma właściwość LicensePlate (string), ustawianą przez konstruktor. Dodaj metodę o nazwie GetBasicInfo(), która zwraca "Vehicle: {LicensePlate}".
  • Car.cs: Zdefiniuj klasę Car w przestrzeni nazw Inspection, która dziedziczy po klasie Vehicle. Samochody mają dodatkową właściwość NumberOfDoors (int). Konstruktor przyjmuje zarówno numer rejestracyjny, jak i liczbę drzwi. Dodaj metodę o nazwie Honk(), która zwraca "{LicensePlate} honks: Beep beep!".
  • Motorcycle.cs: Zdefiniuj klasę Motorcycle w przestrzeni nazw Inspection, która dziedziczy po klasie Vehicle. Motocykle mają właściwość HasSidecar (bool). Konstruktor przyjmuje numer rejestracyjny i informację o obecności wózka bocznego. Dodaj metodę o nazwie Rev(), która zwraca "{LicensePlate} revs: Vroom!".
  • Program.cs: W pliku głównym utworzysz pojazdy i przećwiczysz zarówno rzutowanie w górę, jak i bezpieczne rzutowanie w dół. Utwórz obiekt Car i obiekt Motorcycle na podstawie wprowadzonych wartości, a następnie zapisz oba w tablicy referencji typu Vehicle (rzutowanie w górę). Przejdź przez tablicę i wypisz podstawowe informacje o każdym pojeździe. Następnie użyj słowa kluczowego is z dopasowaniem wzorca, aby bezpiecznie wykonać rzutowanie w dół: jeśli to Car, wywołaj Honk(); jeśli to Motorcycle, wywołaj Rev().

Otrzymasz cztery dane wejściowe:

  • Numer rejestracyjny samochodu
  • Liczba drzwi
  • Numer rejestracyjny motocykla
  • Obecność wózka bocznego (true lub false)

Wypisz wynik w tym formacie dla każdego pojazdu w tablicy:

{GetBasicInfo() result}
{Honk() or Rev() result based on actual type}

Na przykład, jeśli dane wejściowe to ABC-123, 4, XYZ-789 i false, wynik powinien wyglądać tak:

Vehicle: ABC-123
ABC-123 honks: Beep beep!
Vehicle: XYZ-789
XYZ-789 revs: Vroom!

Zwróć uwagę, że wszystkie pojazdy są przechowywane jako referencje typu Vehicle (rzutowanie w górę), ale możesz bezpiecznie rozpoznać ich rzeczywiste typy i uzyskać dostęp do metod specyficznych dla danego typu, używając składni dopasowania wzorca is do rzutowania w dół!

Spróbuj swoich sił

using System;
using Inspection;

class Program
{
    public static void Main(string[] args)
    {
        // Wczytaj dane wejściowe
        string carPlate = Console.ReadLine();
        int numberOfDoors = Convert.ToInt32(Console.ReadLine());
        string motorcyclePlate = Console.ReadLine();
        bool hasSidecar = Convert.ToBoolean(Console.ReadLine());
        
        // TODO: Utwórz obiekt Car, używając carPlate i numberOfDoors
        
        // TODO: Utwórz obiekt Motorcycle, używając motorcyclePlate i hasSidecar
        
        // TODO: Utwórz tablicę referencji typu Vehicle zawierającą oba pojazdy (rzutowanie w górę)
        
        // TODO: Przejdź przez tablicę i dla każdego pojazdu:
        //   - Wypisz wynik GetBasicInfo()
        //   - Użyj słowa kluczowego 'is' z dopasowaniem wzorca, aby bezpiecznie rzutować w dół:
        //     - Jeśli jest to Car, wywołaj Honk() i wypisz wynik
        //     - Jeśli jest to Motorcycle, wywołaj Rev() i wypisz wynik
    }
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C# online