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łaRzutowanie 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.
Wyzwanie
ŁatwyZbudujmy 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ęVehiclew przestrzeni nazwInspection. Każdy pojazd ma właściwośćLicensePlate(string), ustawianą przez konstruktor. Dodaj metodę o nazwieGetBasicInfo(), która zwraca"Vehicle: {LicensePlate}".Car.cs: Zdefiniuj klasęCarw przestrzeni nazwInspection, która dziedziczy po klasieVehicle. Samochody mają dodatkową właściwośćNumberOfDoors(int). Konstruktor przyjmuje zarówno numer rejestracyjny, jak i liczbę drzwi. Dodaj metodę o nazwieHonk(), która zwraca"{LicensePlate} honks: Beep beep!".Motorcycle.cs: Zdefiniuj klasęMotorcyclew przestrzeni nazwInspection, która dziedziczy po klasieVehicle. Motocykle mają właściwośćHasSidecar(bool). Konstruktor przyjmuje numer rejestracyjny i informację o obecności wózka bocznego. Dodaj metodę o nazwieRev(), 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 obiektCari obiektMotorcyclena podstawie wprowadzonych wartości, a następnie zapisz oba w tablicy referencji typuVehicle(rzutowanie w górę). Przejdź przez tablicę i wypisz podstawowe informacje o każdym pojeździe. Następnie użyj słowa kluczowegoisz dopasowaniem wzorca, aby bezpiecznie wykonać rzutowanie w dół: jeśli toCar, wywołajHonk(); jeśli toMotorcycle, wywołajRev().
Otrzymasz cztery dane wejściowe:
- Numer rejestracyjny samochodu
- Liczba drzwi
- Numer rejestracyjny motocykla
- Obecność wózka bocznego (
truelubfalse)
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
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrznePrzestrzenie nazw i dyrektywyWprowadzenie do klas i obiektówSłowo kluczowe „this”Metody i parametryPola a właściwościKonstruktoryInicjalizatory obiektówPodsumowanie — prosty kalkulator4Dziedziczenie
Podstawowa składnia dziedziczenia (:)Słowo kluczowe 'base'Słowa kluczowe virtual i overrideKlasy sealedBazowa klasa 'object'Powtórzenie – hierarchia pracowników7Zaawansowane funkcje
Przeciążanie operatorówIndeksery (this[])Nadpisywanie ToString()Metody rozszerzającePodsumowanie – własna lista2Właściwości i składowe statyczne
Właściwości automatyczneWłaściwości tylko do odczytu i zapisuPola i metody statyczneKlasy statyczneSkładowe z ciałem wyrażeniowym5Polimorfizm i interfejsy
Polimorfizm czasu kompilacji a czasu wykonaniaInterfejs a klasa abstrakcyjnaWiele interfejsówJawne implementowanie interfejsówRzutowanie w górę i w dółPowtórka — kalkulator kształtów8Zaawansowane koncepcje OOP
Kompozycja zamiast dziedziczeniaTypy generyczne (klasy i metody)Delegaty i zdarzeniaAtrybuty i refleksjaIDisposable i instrukcja usingPodstawy wstrzykiwania zależności11Wzorce projektowe, część 2
Wzorzec poleceniaWzorzec adapteraWzorzec dekoratoraWzorzec metody szablonowejWzorzec stanuWzorzec kompozytu3Architektura klas
Dane instancji a dane statyczneSłowa kluczowe 'readonly' i 'const'Pola zapasowePowtórzenie — menedżer kont bankowych6Hermetyzacja
Modyfikatory dostępuWłaściwości w hermetyzacjiImplementacja ukrywania danychWzorce niezmiennościPowtórka — dane studentów9Argumenty zmiennej liczby
Słowo kluczowe „params”Parametry opcjonalneArgumenty nazwanePrzeciążanie metodPoćwicz samodzielnie: Kompilator C# online