MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Metode și proprietăți virtuale

La moștenire, adesea apare necesitatea de a modifica funcționalitatea unei metode moștenite de la clasa de bază în clasa derivată. În acest caz, clasa derivată poate suprascrie metodele și proprietățile clasei de bază.

Metodele și proprietățile pe care dorim să le facem disponibile pentru suprascriere sunt marcate în clasa de bază cu modificatorul virtual. Aceste metode și proprietăți se numesc virtuale.

Pentru a suprascrie o metodă în clasa derivată, aceasta este definită cu modificatorul override. Metoda suprascrisă în clasa derivată trebuie să aibă același set de parametri ca și metoda virtuală din clasa de bază.

De exemplu, să examinăm următoarele clase:

class Person
{
   public string Name { get; set; }
   public Person(string name)
   {
       Name = name;
   }
   public virtual void Print()
   {
       Console.WriteLine(Name);
   }
}
class Employee : Person
{
   public string Company { get; set; }
   public Employee(string name, string company) : base(name)
   {
       Company = company;
   }
}

Aici, clasa Person reprezintă o persoană. Clasa Employee este derivată din Person și reprezintă un angajat al unei companii. Această clasă, pe lângă proprietatea moștenită Name, are încă o proprietate - Company.

Pentru a face metoda Print disponibilă pentru suprascriere, această metodă este definită cu modificatorul virtual. Prin urmare, putem suprascrie această metodă, dar putem și să nu o facem. Să presupunem că ne mulțumește implementarea metodei din clasa de bază.

În acest caz, obiectele Employee vor utiliza implementarea metodei Print din clasa Person:

Person bob = new Person("Bob");
bob.Print(); // apelul metodei Print din clasa Person

Employee tom = new Employee("Tom", "Microsoft");
tom.Print(); // apelul metodei Print din clasa Person

Ieșirea consolă:

Bob
Tom

Dar, de asemenea, putem suprascrie metoda virtuală. Pentru acest lucru, în clasa derivată se definește o metodă cu modificatorul override, care are același nume și set de parametri:

class Employee : Person
{
   public string Company { get; set; }
   public Employee(string name, string company)
       : base(name)
   {
       Company = company;
   }
   public override void Print()
   {
       Console.WriteLine($"{Name} lucrează la {Company}");
   }
}

Să luăm aceleași obiecte:

Person bob = new Person("Bob");
bob.Print(); // apelul metodei Print din clasa Person

Employee tom = new Employee("Tom", "Microsoft");
tom.Print(); // apelul metodei Print din clasa Employee

Ieșirea consolă:

Bob
Tom lucrează la Microsoft

Metodele virtuale ale clasei de bază definesc interfața întregii ierarhii, adică în orice clasă derivată, care nu este un descendent direct al clasei de bază, se pot suprascrie metodele virtuale. De exemplu, putem defini clasa Manager, care va fi derivată din Employee, și în ea, de asemenea, putem suprascrie metoda Print.

La suprascrierea metodelor virtuale trebuie să ținem cont de câteva restricții:

  • Metodele virtuale și cele suprascrise trebuie să aibă același modificator de acces. Adică, dacă metoda virtuală este definită cu ajutorul modificatorului public, atunci și metoda suprascrisă trebuie să aibă modificatorul public
  • Nu se poate suprascrie sau declara ca virtuală o metodă statică

Cuvântul cheie base

Pe lângă constructori, putem accesa cu ajutorul cuvântului cheie base și alți membri ai clasei de bază. În cazul nostru, apelul base.Print(); va fi o referire la metoda Print() în clasa Person:

class Employee : Person
{
   public string Company { get; set; }
 
   public Employee(string name, string company)
           :base(name)
   {
       Company = company;
   }
 
   public override void Print()
   {
       base.Print();
       Console.WriteLine($"lucrează la {Company}");
   }
}

Suprascrierea proprietăților

La fel ca metodele, se pot suprascrie și proprietățile:

class Person
{
   int age = 1;
   public virtual int Age
   {
       get => age;
       set{ if(value > 0 && value < 110) age = value; }
   }
   public string Name { get; set; }
   public Person(string name)
   {
       Name = name;
   }
   public virtual void Print() => Console.WriteLine(Name);
}
class Employee : Person
{
   public override int Age
   {
       get => base.Age;
       set { if (value > 17 && value < 110) base.Age = value; }
   }
   public string Company { get; set; }
   public Employee(string name, string company)
       : base(name)
   {
       Company = company;
       base.Age = 18; // vârsta implicită pentru angajați
   }
}

În acest caz, în clasa Person este definită proprietatea virtuală Age, care setează valoarea dacă este mai mare de 0 și mai mică de 110. În clasa Employee, această proprietate este suprascrisă - vârsta unui angajat trebuie să fie nu mai mică de 18.

Person bob = new Person("Bob");
Console.WriteLine(bob.Age); // 1

Employee tom = new Employee("Tom", "Microsoft");
Console.WriteLine(tom.Age); // 18
tom.Age = 22;
Console.WriteLine(tom.Age); // 22
tom.Age = 12;
Console.WriteLine(tom.Age); // 22

Interzicerea suprascrierii metodelor

De asemenea, se poate interzice suprascrierea metodelor și proprietăților. În acest caz, acestea trebuie declarate cu modificatorul sealed:

class Employee : Person
{
   public string Company { get; set; }
 
   public Employee(string name, string company)
               : base(name)
   {
       Company = company;
   }

   public override sealed void Print()
   {
       Console.WriteLine($"{Name} lucrează la {Company}");
   }
}

Când se creează metode cu modificatorul sealed, trebuie să ținem cont că sealed se aplică în pereche cu override, adică numai în metodele suprascrise.

Și în acest caz nu vom putea suprascrie metoda Print în clasa care este moștenită de la Employee.

← Lecția anterioară Lecția următoare →