Содержание
При использовании механизма наследовании в C# достаточно часто появляется необходимость изменить в классе-наследнике функционал метода, который был унаследован от предка (базового класса). Для этого, в C# класс-наследник может переопределять методы и свойства базового класса. Те методы или свойства, которые мы хотим сделать доступными для переопределения, в базовом классе помечается модификатором virtual. Такие методы и свойства обычно называют виртуальными.
Переопределение методов в C#
Чтобы переопределить метод в классе-наследнике, этот метод определяется с в классе модификатором override. В отличие от перегрузки, переопределенный метод в классе-наследнике должен иметь тот же набор параметров, что и виртуальный метод в базовом классе. Например, рассмотрим следующие классы:
class Person
{
public string Name { get; set; }
public Person(string name)
{
Name = name;
}
public virtual void Display()
{
Console.WriteLine(Name);
}
}
class Employee : Person
{
public string Company { get; set; }
public Employee(string name, string company) : base(name)
{
Company = company;
}
}
Класс Person представляет человека. В свою очередь, класс Employee наследуется от Person и представляет сотрудника организации и, кроме унаследованного свойства Name, имеет еще одно свойство — Company. Чтобы сделать метод Display доступным для переопределения, этот метод определен с модификатором virtual, что и было сделано в примере. Поэтому мы можем переопределить этот метод (а можем и не переопределять — всё зависит от наших потребностей).
Допустим, что нас устраивает реализация метода из базового класса. В таком случае, объекты Employee будут использовать реализацию метода Display из класса Personкак есть:
Person p1 = new Person("Вася");
p1.Display(); // вызов метода Display из класса Person
Employee e1 = new Employee("Билл", "Microsoft");
e1.Display(); // вызов метода Display из класса Person
В консоли мы увидим следующее:
Билл
Если же нас не устраивает функционал метода Display в родителе, то мы можем переопределить виртуальный метод. Для этого в классе-наследнике определяется метод с модификатором override, который имеет то же самое имя и набор параметров (сигнатуру):
class Employee : Person
{
public string Company { get; set; }
public Employee(string name, string company): base(name)
{
Company = company;
}
public override void Display()
{
Console.WriteLine($"{Name} работает в {Company}");
}
}
Пример использования:
Person p1 = new Person("Bill");
p1.Display(); // вызов метода Display из класса Person
Employee p2 = new Employee("Tom", "Microsoft");
p2.Display(); // вызов метода Display из класса Employee
В консоли будут следующие строки:
Tom работает в Microsoft
Виртуальные методы базового класса определяют интерфейс всей иерархии классов. Это значит, что в любом производном классе, который не является прямым наследником от базового класса, можно переопределить виртуальные методы. Например, мы можем определить класс Manager, который будет производным от Employee, и в нем также переопределить метод Display.
При переопределении виртуальных методов в C# необходимо учитывать следующие ограничения:
- Виртуальный и переопределенный методы должны иметь один и тот же модификатор доступа. Если виртуальный метод определен с помощью модификатора
public, то и переопределенный метод также должен иметь модификаторpublic. - Нельзя переопределить или объявить виртуальным статический метод.
Переопределение свойств в C#
В C# можно переопределять как методы, так и свойства базовых классов:
class Credit
{
public virtual decimal Sum { get; set; }
}
class LongCredit : Credit
{
private decimal sum;
//переопределенное свойство
public override decimal Sum
{
get
{
return sum;
}
set
{
if(value > 1000)
{
sum = value;
}
}
}
}
class Program
{
static void Main(string[] args)
{
LongCredit credit = new LongCredit { Sum = 6000 };
credit.Sum = 490;
Console.WriteLine(credit.Sum);
}
}
Ключевое слово base
С использованием ключевого слова base мы можем обращаться к членам базового класса. В нашем случае вызов base.Display(); позволяет обратиться к методу Display() в классе Person:
class Employee : Person
{
public string Company { get; set; }
public Employee(string name, string company)
:base(name)
{
Company = company;
}
public override void Display()
{
base.Display();
Console.WriteLine($"работает в {Company}");
}
}
Запрет переопределения методов
Бывает необходимо также запретить переопределение методов и свойств в классах-наследниках. В этом случае методы и свойства необходимо объявлять с модификатором sealed:
class Employee : Person
{
public string Company { get; set; }
public Employee(string name, string company): base(name)
{
Company = company;
}
//ни один наследник Employee не сможет переопределить этот метод
public override sealed void Display()
{
Console.WriteLine($"{Name} работает в {Company}");
}
}
При создании методов с модификатором sealed следует учитывать, что ключевое слово sealed применяется в паре с override, то есть только в переопределяемых методах.
Итого
Сегодня мы познакомились с такой замечательной возможностью языка C# как переопределение методов и свойств. Узнали как определять в классах виртуальные методы, переопределять методы и свойства в наследниках, а также обращаться к членам и методам базовых классов, используя ключевое слово base и запрещать переопределять методы с использованием ключевого слова sealed.