Ce face Moștenire: virtual, override și base
În C# o clasă moștenește dintr-o singură clasă de bază, scrisă după două puncte: class Student : Persoana. Clasa derivată primește câmpurile, proprietățile și metodele accesibile ale bazei și poate adăuga altele. Un obiect Student poate fi folosit oriunde se așteaptă o Persoana.
O metodă poate fi înlocuită în clasa derivată doar dacă baza o marchează virtual (sau abstract); derivata scrie override. Apelul se decide la rulare, după tipul real al obiectului (polimorfism). Cu base.Metoda() derivata poate refolosi implementarea bazei, iar : base(...) la constructor trimite argumente constructorului bazei.
Fără override, o metodă cu același nume ascunde metoda bazei (cuvântul new, cu avertismentul CS0108 dacă lipsește), iar apelul printr-o variabilă de tipul bazei ajunge la metoda bazei. De obicei asta nu e ce vrei.
Exemple
Exemplul 1: Polimorfism cu virtual și override
List<Angajat> echipa =
[
new Angajat("Ana", 6000),
new Manager("Mihai", 9000, 2000),
];
foreach (Angajat a in echipa)
Console.WriteLine($"{a.Nume}: {a.Salariu()} lei");
class Angajat(string nume, int baza)
{
public string Nume { get; } = nume;
protected int Baza { get; } = baza;
public virtual int Salariu() => Baza;
}
class Manager(string nume, int baza, int bonus) : Angajat(nume, baza)
{
public override int Salariu() => base.Salariu() + bonus;
}
Rezultat
Ana: 6000 lei
Mihai: 11000 lei
Exemplul 2: override față de new (ascundere)
Prin variabila de tip Animal, doar metoda cu override ajunge la clasa derivată.
Animal a1 = new Caine();
Animal a2 = new Pisica();
Console.WriteLine(a1.Sunet());
Console.WriteLine(a2.Sunet());
Console.WriteLine(new Pisica().Sunet());
class Animal
{
public virtual string Sunet() => "...";
}
class Caine : Animal
{
public override string Sunet() => "Ham";
}
class Pisica : Animal
{
public new string Sunet() => "Miau";
}
Rezultat
Ham
...
Miau
Greșeli frecvente
- Uitarea lui
virtualîn bază:overridedă eroarea CS0506, iar fără el metoda doar ascunde baza. - Moștenirea multiplă de clase nu există în C#:
class C : A, Bmerge doar dacăBeste interfață. - Moștenirea folosită doar ca să refolosești cod duce la ierarhii fragile. Când relația nu este „este un/o”, preferă compunerea (un câmp de tipul celeilalte clase) sau o interfață.
Comenzi înrudite
abstract (clase și metode abstracte): O clasă abstract nu poate fi instanțiată direct; metodele abstract nu au corp și trebuie implementate de fiecare clasă derivată.sealed: Interzice moștenirea unei clase sau suprascrierea mai departe a unei metode override.Constructori (this, supraîncărcare, static): Constructorul inițializează un obiect creat cu new; poate avea variante, poate apela altă variantă cu : this(…) și există și constructor static.