Jestem nowy w C # (i OOP ). Kiedy mam kod podobny do następującego:
class Employee
{
// some code
}
class Manager : Employee
{
//some code
}
Pytanie 1 : Jeśli mam inny kod, który to robi:
Manager mgr = new Manager();
Employee emp = (Employee)mgr;
Oto Employee
a Manager
, ale kiedy Employee
rzucam to w ten sposób na to, oznacza to, że go podrzucam?
Pytanie 2 :
Kiedy mam kilka Employee
obiektów klasowych, a niektóre z nich są, ale nie wszystkie Manager
, jak mogę je zdegradować, jeśli to możliwe?
Employee emp= mgr;
powinno wystarczyć.Odpowiedzi:
To jest poprawne. Kiedy to robisz, wrzucasz go do
employee
obiektu, co oznacza, że nie możesz uzyskać dostępu do niczego konkretnego menedżera.Downcasting polega na tym, że bierzesz klasę bazową, a następnie próbujesz przekształcić ją w bardziej szczegółową klasę. Można to osiągnąć za pomocą is i wyraźnego rzutowania w następujący sposób:
if (employee is Manager) { Manager m = (Manager)employee; //do something with it }
lub z takim
as
operatorem:Manager m = (employee as Manager); if (m != null) { //do something with it }
Jeśli coś jest niejasne, z przyjemnością to poprawię!
źródło
as
operatora zamiastis
, po którym następuje rzutowanie.Uaktualnianie (używanie
(Employee)someInstance
) jest ogólnie łatwe, ponieważ kompilator może powiedzieć w czasie kompilacji, czy typ pochodzi od innego.Jednak generowanie downcastingu musi być wykonywane w czasie wykonywania, ponieważ kompilator może nie zawsze wiedzieć, czy dana instancja jest podanego typu. C # udostępnia dwa podmioty do tego - to , które mówi, jeśli prace spuszczonymi i powrócić prawda / fałsz. I jak który próbuje wykonać rzutowanie i zwraca poprawny typ, jeśli to możliwe, lub null, jeśli nie.
Aby sprawdzić, czy pracownik jest menedżerem:
Employee m = new Manager(); Employee e = new Employee(); if(m is Manager) Console.WriteLine("m is a manager"); if(e is Manager) Console.WriteLine("e is a manager");
Możesz również użyć tego
Employee someEmployee = e as Manager; if(someEmployee != null) Console.WriteLine("someEmployee (e) is a manager"); Employee someEmployee = m as Manager; if(someEmployee != null) Console.WriteLine("someEmployee (m) is a manager");
źródło
W Twoim przypadku
Employee emp = (Employee)mgr; //mgr is Manager
robisz upcasting.
Upcast zawsze kończy się sukcesem, w przeciwieństwie do downcast, który wymaga jawnego rzutowania, ponieważ może potencjalnie zakończyć się niepowodzeniem w czasie wykonywania ( InvalidCastException ).
C # oferuje dwa operatory, aby uniknąć wyrzucenia tego wyjątku:
Zaczynając od:
Employee e = new Employee();
Pierwszy:
Manager m = e as Manager; // if downcast fails m is null; no exception thrown
Druga:
if (e is Manager){...} // the predicate is false if the downcast is not possible
Ostrzeżenie : kiedy robisz upcast, masz dostęp tylko do metod, właściwości nadklasy itp ...
źródło
W przypadku konieczności sprawdzenia każdego obiektu Employee, czy jest to obiekt Manager, użyj metody OfType:
List<Employee> employees = new List<Employee>(); //Code to add some Employee or Manager objects.. var onlyManagers = employees.OfType<Manager>(); foreach (Manager m in onlyManagers) { // Do Manager specific thing.. }
źródło
Odpowiedź 1: Tak, nazywa się to upcastingiem, ale sposób, w jaki to robisz, nie jest nowoczesny. Nadawanie można wykonać niejawnie, nie potrzebujesz żadnej konwersji. Więc po prostu piszesz Pracownik emp = mgr; wystarczy do podniecenia.
Odpowiedź 2: Jeśli tworzysz obiekt klasy Manager, możemy powiedzieć, że menedżer jest pracownikiem. Ponieważ klasa Manager: Employee przedstawia relację IS -A pomiędzy klasą pracownika a klasą menedżera. Można więc powiedzieć, że każdy menedżer jest pracownikiem.
Ale jeśli tworzymy obiekt klasy Employee, nie możemy powiedzieć, że ten pracownik jest menedżerem, ponieważ klasa Employee to klasa, która nie dziedziczy żadnej innej klasy. Dlatego nie można bezpośrednio przenieść tego obiektu klasy pracownika do obiektu klasy menedżera.
Więc odpowiedź jest taka, że jeśli chcesz zdegradować obiekt klasy pracownika do obiektu klasy menedżera, najpierw musisz mieć obiekt klasy menedżera, następnie możesz go przesłać do góry, a następnie możesz go zdegradować.
źródło
Upcasting i Downcasting:
Upcasting: rzutowanie z klasy pochodnej do klasy podstawowej. Downcasting: rzutowanie z klasy bazowej do klasy pochodnej
Rozumiemy to samo, co na przykładzie:
Rozważ dwie klasy Shape jako Moja klasa nadrzędna i Circle jako klasę pochodną, zdefiniowane w następujący sposób:
class Shape { public int Width { get; set; } public int Height { get; set; } } class Circle : Shape { public int Radius { get; set; } public bool FillColor { get; set; } }
Nadawanie:
Kształt s = nowy Kształt ();
Okrąg c = s;
Zarówno c, jak i s odnoszą się do tej samej lokalizacji w pamięci, ale oba mają różne widoki tzn. Używając odwołania "c" możesz również uzyskać dostęp do wszystkich właściwości klasy bazowej i pochodnej, ale używając odnośnika "s" możesz uzyskać dostęp do właściwości jedynej klasy nadrzędnej.
Praktycznym przykładem upcastingu jest klasa Stream, która jest klasą bazową wszystkich typów czytników strumieniowych frameworka .net:
StreamReader reader = new StreamReader (new FileStreamReader ());
tutaj FileStreamReader () jest upcastowany do reder streadm.
Downcasting:
Kształt s = nowy okrąg (); tutaj, jak wyjaśniono powyżej, widok s jest jedynym rodzicem, aby uczynić go zarówno dla rodzica, jak i dziecka, musimy go obniżyć
var c = (Circle) s;
Praktycznym przykładem Downcasting jest klasa przycisku WPF.
źródło