Ascunderea metodelor și proprietăților
În tema anterioară, am discutat despre definirea și suprascrierea metodelor virtuale. O altă metodă de a modifica funcționalitatea unei metode moștenite de la clasa de bază este ascunderea (shadowing / hiding).
Ascunderea unei metode sau proprietăți implică definirea în clasa derivată a unei metode sau proprietăți care corespunde ca nume și set de parametri cu metoda sau proprietatea clasei de bază. Pentru ascunderea membrilor clasei se utilizează cuvântul cheie new. De exemplu:
class Person
{
public string Name { get; set; }
public Person(string name)
{
Name = name;
}
public void Print()
{
Console.WriteLine($"Name: {Name}");
}
}
class Employee : Person
{
public string Company { get; set; }
public Employee(string name, string company) : base(name)
{
Company = company;
}
public new void Print()
{
Console.WriteLine($"Name: {Name} Company: {Company}");
}
}
Aici este definită clasa Person, care reprezintă o persoană, și clasa Employee, care reprezintă un angajat al unei companii. Employee moștenește toate proprietățile și metodele de la Person. Dar în clasa Employee, pe lângă proprietățile moștenite, există și proprietatea proprie Company, care stochează numele companiei.
Și dorim ca metoda Print să afișeze informații despre companie împreună cu numele pe consolă. Pentru aceasta, se definește metoda Print cu cuvântul cheie new, care ascunde implementarea acestei metode din clasa de bază.
În ce situații putem folosi ascunderea? De exemplu, în exemplul de mai sus, metoda Print în clasa de bază nu este virtuală, deci nu o putem suprascrie, dar presupunem că implementarea ei nu ne satisface pentru clasa derivată, deci putem folosi ascunderea pentru a defini funcționalitatea necesară.
Utilizarea acestor clase în program în metoda Main:
Person bob = new Person("Bob");
bob.Print(); // Name: Bob
Employee tom = new Employee("Tom", "Microsoft");
tom.Print(); // Name: Tom Company: Microsoft
Ieșirea consolă a programului:
Name: Bob
Name: Tom Company: Microsoft
Dacă dorim să accesăm în mod explicit implementarea proprietății sau metodei din clasa de bază, putem folosi cuvântul cheie base pentru a accesa funcționalitatea clasei de bază.
class Employee : Person
{
public string Company { get; set; }
public Employee(string name, string company) : base(name)
{
Company = company;
}
public new void Print()
{
base.Print(); // apelăm metoda Print din clasa de bază Person
Console.WriteLine($"Company: {Company}");
}
}
Ascunderea proprietăților
La fel, putem organiza ascunderea proprietăților:
Person bob = new Person("Bob");
Console.WriteLine(bob.Name); // Bob
Employee tom = new Employee("Tom", "Microsoft");
Console.WriteLine(tom.Name); // Mr./Ms. Tom
class Person
{
public string Name { get; set; }
public Person(string name)
{
Name = name;
}
}
class Employee : Person
{
// ascundem proprietatea Name a clasei de bază
public new string Name
{
get => $"Mr./Ms. {base.Name}";
set => base.Name = value;
}
public string Company { get; set; }
public Employee(string name, string company) : base(name)
{
Company = company;
}
}
În acest caz, în clasa Employee este suprascrisă proprietatea Name. În blocul get, luăm valoarea proprietății din clasa de bază Person și adăugăm "Mr./Ms.". În blocul set, transmitem valoarea primită implementării proprietății Name din clasa de bază Person.
Ascunderea variabilelor și constantelor
Spre deosebire de suprascriere, C# permite aplicarea ascunderii și la variabile (atat statice, cât și non-statice) și constante, folosind de asemenea cuvântul cheie new:
Console.WriteLine(Person.minAge); // 1
Console.WriteLine(Person.typeName); // Person
Console.WriteLine(Employee.minAge); // 18
Console.WriteLine(Employee.typeName); // Employee
class Person
{
public readonly static int minAge = 1;
public const string typeName = "Person";
}
class Employee : Person
{
// ascundem câmpurile și constantele clasei de bază
public new readonly static int minAge = 18;
public new const string typeName = "Employee";
}