Переопределение методов си шарп

override (C# reference)

The override modifier is required to extend or modify the abstract or virtual implementation of an inherited method, property, indexer, or event.

In the following example, the Square class must provide an overridden implementation of GetArea because GetArea is inherited from the abstract Shape class:

abstract class Shape < public abstract int GetArea(); >class Square : Shape < private int _side; public Square(int n) =>_side = n; // GetArea method is required to avoid a compile-time error. public override int GetArea() => _side * _side; static void Main() < var sq = new Square(12); Console.WriteLine($"Area of the square = "); > > // Output: Area of the square = 144 

An override method provides a new implementation of the method inherited from a base class. The method that is overridden by an override declaration is known as the overridden base method. An override method must have the same signature as the overridden base method. override methods support covariant return types. In particular, the return type of an override method can derive from the return type of the corresponding base method.

You cannot override a non-virtual or static method. The overridden base method must be virtual , abstract , or override .

An override declaration cannot change the accessibility of the virtual method. Both the override method and the virtual method must have the same access level modifier.

You cannot use the new , static , or virtual modifiers to modify an override method.

Читайте также:  Королевский питон максимальный размер

An overriding property declaration must specify exactly the same access modifier, type, and name as the inherited property. Beginning with C# 9.0, read-only overriding properties support covariant return types. The overridden property must be virtual , abstract , or override .

For more information about how to use the override keyword, see Versioning with the Override and New Keywords and Knowing when to use Override and New Keywords. For information about inheritance, see Inheritance.

Example

This example defines a base class named Employee , and a derived class named SalesEmployee . The SalesEmployee class includes an extra field, salesbonus , and overrides the method CalculatePay in order to take it into account.

class TestOverride < public class Employee < public string Name < get; >// Basepay is defined as protected, so that it may be // accessed only by this class and derived classes. protected decimal _basepay; // Constructor to set the name and basepay values. public Employee(string name, decimal basepay) < Name = name; _basepay = basepay; >// Declared virtual so it can be overridden. public virtual decimal CalculatePay() < return _basepay; >> // Derive a new class from Employee. public class SalesEmployee : Employee < // New field that will affect the base pay. private decimal _salesbonus; // The constructor calls the base-class version, and // initializes the salesbonus field. public SalesEmployee(string name, decimal basepay, decimal salesbonus) : base(name, basepay) < _salesbonus = salesbonus; >// Override the CalculatePay method // to take bonus into account. public override decimal CalculatePay() < return _basepay + _salesbonus; >> static void Main() < // Create some new employees. var employee1 = new SalesEmployee("Alice", 1000, 500); var employee2 = new Employee("Bob", 1200); Console.WriteLine($"Employee1 earned: "); Console.WriteLine($"Employee2 earned: "); > > /* Output: Employee1 Alice earned: 1500 Employee2 Bob earned: 1200 */ 

C# language specification

For more information, see the Override methods section of the C# language specification.

For more information about covariant return types, see the feature proposal note.

Источник

Переопределение методов си шарп

При наследовании нередко возникает необходимость изменить в классе-наследнике функционал метода, который был унаследован от базового класса. В этом случае класс-наследник может переопределять методы и свойства базового класса.

Те методы и свойства, которые мы хотим сделать доступными для переопределения, в базовом классе помечается модификатором virtual . Такие методы и свойства называют виртуальными.

А чтобы переопределить метод в классе-наследнике, этот метод определяется с модификатором override . Переопределенный метод в классе-наследнике должен иметь тот же набор параметров, что и виртуальный метод в базовом классе.

Например, рассмотрим следующие классы:

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; >>

Здесь класс Person представляет человека. Класс Employee наследуется от Person и представляет сотруднника предприятия. Этот класс кроме унаследованного свойства Name имеет еще одно свойство — Company.

Чтобы сделать метод Print доступным для переопределения, этот метод определен с модификатором virtual . Поэтому мы можем переопределить этот метод, но можем и не переопределять. Допустим, нас устраивает реализация метода из базового класса. В этом случае объекты Employee будут использовать реализацию метода Print из класса Person:

Person bob = new Person("Bob"); bob.Print(); // вызов метода Print из класса Person Employee tom = new Employee("Tom", "Microsoft"); tom.Print(); // вызов метода Print из класса Person

Но также можем переопределить виртуальный метод. Для этого в классе-наследнике определяется метод с модификатором override , который имеет то же самое имя и набор параметров:

class Employee : Person < public string Company < get; set; >public Employee(string name, string company) : base(name) < Company = company; >public override void Print() < Console.WriteLine($"работает в "); > >

Возьмем те же самые объекты:

Person bob = new Person("Bob"); bob.Print(); // вызов метода Print из класса Person Employee tom = new Employee("Tom", "Microsoft"); tom.Print(); // вызов метода Print из класса Employee
Bob Tom работает в Microsoft

Виртуальные методы базового класса определяют интерфейс всей иерархии, то есть в любом производном классе, который не является прямым наследником от базового класса, можно переопределить виртуальные методы. Например, мы можем определить класс Manager, который будет производным от Employee, и в нем также переопределить метод Print.

При переопределении виртуальных методов следует учитывать ряд ограничений:

  • Виртуальный и переопределенный методы должны иметь один и тот же модификатор доступа. То есть если виртуальный метод определен с помощью модификатора public, то и переопредленный метод также должен иметь модификатор public.
  • Нельзя переопределить или объявить виртуальным статический метод.

Ключевое слово base

Кроме конструкторов, мы можем обратиться с помощью ключевого слова base к другим членам базового класса. В нашем случае вызов base.Print(); будет обращением к методу Print() в классе 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($"работает в "); > >

Переопределение свойств

Также как и методы, можно переопределять свойства:

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; // возраст для работников по умолчанию >>

В данном случае в классе Person определено виртуальное свойство Age, которое устанавливает значение, если оно больше 0 и меньше 110. В классе Employee это свойство переопределено — возраст работника должен быть не меньше 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

Запрет переопределения методов

Также можно запретить переопределение методов и свойств. В этом случае их надо объявлять с модификатором 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($"работает в "); > >

При создании методов с модификатором sealed надо учитывать, что sealed применяется в паре с override, то есть только в переопределяемых методах.

И в этом случае мы не сможем переопределить метод Print в классе, унаследованном от Employee.

Источник

override (справочник по C#)

Модификатор override требуется для расширения или изменения абстрактной или виртуальной реализации унаследованного метода, свойства, индексатора или события.

В следующем примере класс Square должен предоставить переопределенную реализацию GetArea , так как GetArea является унаследованным от абстрактного класса Shape :

abstract class Shape < public abstract int GetArea(); >class Square : Shape < private int _side; public Square(int n) =>_side = n; // GetArea method is required to avoid a compile-time error. public override int GetArea() => _side * _side; static void Main() < var sq = new Square(12); Console.WriteLine($"Area of the square = "); > > // Output: Area of the square = 144 

Метод override предоставляет новую реализацию метода, унаследованного от базового класса. Метод, переопределенный объявлением override , называется переопределенным базовым методом. Метод override должен иметь ту же сигнатуру, что и переопределенный базовый метод. override методы поддерживают ковариантные возвращаемые типы. В частности, тип возвращаемого значения метода override может быть производным от типа возвращаемого значения соответствующего базового метода.

Невиртуальный или статический метод нельзя переопределить. Переопределенный базовый метод должен иметь тип virtual , abstract или override .

Объявление override не может изменить доступность метода virtual . Методы override и virtual должны иметь одинаковый модификатор уровня доступа.

Модификаторы new , static и virtual нельзя использовать для изменения метода override .

Переопределяющее объявление свойства должно задавать такие же модификатор уровня доступа, тип и имя, которые имеются у унаследованного свойства. Начиная с версии C# 9.0, переопределяющие свойства только для чтения поддерживают ковариантные типы возвращаемых значений. Переопределенное свойство должно быть virtual , abstract или override .

Дополнительные сведения об использовании ключевого слова override см. в разделах Управление версиями с помощью ключевых слов Override и New и Использование ключевых слов Override и New. Дополнительные сведения о наследовании см. в разделе Наследование.

Пример

В этом примере определяется базовый класс с именем Employee и производный класс с именем SalesEmployee . Класс SalesEmployee включает дополнительное поле salesbonus , для использования которого переопределяется метод CalculatePay .

class TestOverride < public class Employee < public string Name < get; >// Basepay is defined as protected, so that it may be // accessed only by this class and derived classes. protected decimal _basepay; // Constructor to set the name and basepay values. public Employee(string name, decimal basepay) < Name = name; _basepay = basepay; >// Declared virtual so it can be overridden. public virtual decimal CalculatePay() < return _basepay; >> // Derive a new class from Employee. public class SalesEmployee : Employee < // New field that will affect the base pay. private decimal _salesbonus; // The constructor calls the base-class version, and // initializes the salesbonus field. public SalesEmployee(string name, decimal basepay, decimal salesbonus) : base(name, basepay) < _salesbonus = salesbonus; >// Override the CalculatePay method // to take bonus into account. public override decimal CalculatePay() < return _basepay + _salesbonus; >> static void Main() < // Create some new employees. var employee1 = new SalesEmployee("Alice", 1000, 500); var employee2 = new Employee("Bob", 1200); Console.WriteLine($"Employee1 earned: "); Console.WriteLine($"Employee2 earned: "); > > /* Output: Employee1 Alice earned: 1500 Employee2 Bob earned: 1200 */ 

Спецификация языка C#

Дополнительные сведения см. в разделе Методы переопределения статьи Спецификация языка C#.

Дополнительные сведения о ковариантных типах возвращаемых значений см. в примечании к функциям.

См. также

Источник

Переопределение методов си шарп

Ранее было рассмотрена два способа изменения функциональности методов, унаследованных от базового класса — скрытие и переопределение. В чем разница между двумя этими способами?

Переопределение

Возьмем пример с переопределением методов:

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; >public override void Print() < Console.WriteLine($"работает в "); > >

Используем классы в программе:

Person tom = new Employee("Tom", "Microsoft"); tom.Print(); // Tom работает в Microsoft

При вызове tom.Print() выполняется реализация метода Print из класса Employee, несмотря на то, что переменная tom — переменная типа Person.

Для работы с виртуальными методами компилятор формирует таблицу виртуальных методов ( Virtual Method Table или VMT ). В нее записывается адреса виртуальных методов. Для каждого класса создается своя таблица.

Когда создается объект класса, то компилятор передает в конструктор объекта специальный код, который связывает объект и таблицу VMT.

А при вызове виртуального метода из объекта берется адрес его таблицы VMT. Затем из VMT извлекается адрес метода и ему передается управление. То есть процесс выбора реализации метода производится во время выполнения программы. Собственно так и выполняется виртуальный метод. Следует учитывать, что так как среде выполнения вначале необходимо получить из таблицы VMT адрес нужного метода, то это немного замедляет выполнение программы.

Скрытие

Теперь возьмем те же классы Person и Employee, но вместо переопределения используем сокрытие:

class Person < public string Name < get; set; >public Person(string name) < Name = name; >public void Print() < Console.WriteLine(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($"работает в "); > >

И посмотрим, что будет в следующем случае:

Person tom = new Employee("Tom", "Microsoft"); tom.Print(); // Tom

Переменная tom представляет тип Person, но хранит ссылку на объект Employee. Однако при вызове метода Print будет выполняться та версия метода, которая определена именно в классе Person, а не в классе Employee. Почему? Класс Employee никак не переопределяет метод Print, унаследованный от базового класса, а фактически определяет новый метод. Поэтому при вызове tom.Print() вызывается метод Print из класса Person.

Источник

Оцените статью