Доступен файл Class-> Inheritance в ExampleBook Мы можем передавать экземпляр дочернего класса вместо родительского. Однако нужно учесть, что принимаемая сущность (например метод) будет оперировать только теми member’ами, которые были определены в родительском классе. При этом, если родительские member’ы были переопределены (override) дочерним классом, то сущность будет пользоваться реализацией дочернего. Про существование дочерних member’ов, которых нет в родительском, сущность знать не будет, потому что он будет думать, что работает с родителем, а не с дочкой. При этом, можно будет в дальнейшем дочку в теле родителя закаставать (casting) и вернуть экземпляру дочки «лицо» дочки, чтобы все member’ы дочки стали доступы для использования. Нет «прямого» наследования операторов. Это обусловлено тем, что операторы в C# статические, а статические члены не участвуют в механизме наследования. Но вы всё равно можете определить или переопределить операторы в вашем дочернем классе. В C# статические методы не могут быть объявлены как **abstract** или **virtual**. Статический метод в C# принадлежит классу, а не конкретному экземпляру класса. По этой причине они не могут быть переопределены, что является основной функцией виртуальных методов. ##### как заставить потомка переопределить метод, если родитель метод реализовал? В C# вы не можете "заставить" класс-наследник переопределить метод, который уже был реализован в базовом классе. ##### Какие есть способы переопределения детьми родительских методов? В C# для переопределения родительских методов доступны следующие ключевые слова: 1. **virtual**: Методы, объявленные в базовом классе как virtual, **могут быть** переопределены в производных классах. 2. **abstract**: Методы, объявленные в базовом классе как abstract, **должны быть** переопределены в производных классах. Базовый класс с абстрактными методами также должен быть объявлен как abstract. 3. **override**: Это ключевое слово используется в производном классе для переопределения метода, объявленного в базовом классе как virtual, abstract или override. 4. **new** (или **hiding**): Используется для "скрытия" метода, наследуемого от базового класса. В этом случае, метод в производном классе имеет ту же сигнатуру, что и в базовом классе, но он не помечен как override, поэтому он не "видит" метод базового класса. По сути, он "скрывает" метод базового класса. При использовании ключевого слова new предупреждение компилятора об отсутствии override будет подавлено. Редко используется разработчиками на практике. ##### а в чем разница между модификатором new и override? new не предоставляет полиморфное поведение, которое обычно ассоциируется с переопределением методов с помощью модификатора override. Если метод дочернего класса скрывает метод родительского класса с использованием модификатора new и затем экземпляр дочернего класса используется через ссылку на родительский класс, то вызовется метод родительского класса. <br> Мой пример Если закастовать ребенка в родителя и вызвать метод, который есть в родителе, но был переопределен ребенком, то выполнится метод, который реализовал ребенок. <u>Скрытие (Hiding)</u> Основывается на типе ссылки, а не на реальном типе объекта. Это называется "статическим связыванием" или "ранним связыванием". Мой пример То же самое, но если метод был скрыт, а не переопределен, то выполнится реализация родительского метода. <br> ##### Если реализовать override метод, то будет ли выполняться метод родителя? Когда вы переопределяете метод в производном классе с использованием ключевого слова override, метод родительского класса не будет автоматически вызываться. Вам нужно явно вызвать метод родительского класса с помощью ключевого слова base, если вы хотите, чтобы он выполнялся в дополнение к вашей реализации в производном классе. ```csharp public class ParentClass { public virtual void MyMethod() { Console.WriteLine("ParentClass MyMethod"); } } public class ChildClass : ParentClass { public override void MyMethod() { base.MyMethod(); // Явный вызов родительского метода Console.WriteLine("ChildClass MyMethod"); } } ``` ##### А если переопределить метод, который уже переопределен? Если вы переопределяете метод, который уже был переопределен в другом классе, вы переопределяете метод из ближайшего родительского класса в иерархии наследования. ```csharp public class GrandparentClass { public virtual void MyMethod() { Console.WriteLine("GrandparentClass MyMethod"); } } public class ParentClass : GrandparentClass { public override void MyMethod() { Console.WriteLine("ParentClass MyMethod"); } } public class ChildClass : ParentClass { public override void MyMethod() { Console.WriteLine("ChildClass MyMethod"); } } ``` В этом примере ChildClass переопределяет метод MyMethod(), который был переопределен в ParentClass. В данном случае, при вызове MyMethod() на объекте типа ChildClass, будет выполнен метод из ChildClass, а не из ParentClass или GrandparentClass. Если вы хотите вызвать метод из родительского класса (например, ParentClass), вы можете использовать ключевое слово base: ```csharp public class ChildClass : ParentClass { public override void MyMethod() { base.MyMethod(); // Вызов метода из ParentClass Console.WriteLine("ChildClass MyMethod"); } } ``` Таким образом, при вызове MyMethod() на объекте типа ChildClass, сначала будет выполнен метод из ParentClass, а затем метод из ChildClass. Если вы хотите вызвать метод из GrandparentClass, вы должны явно вызвать его из метода ParentClass, используя base.MyMethod() в его реализации.