Наследование и полиморфизм
Наследование является одним из принципов ООП.
Основы классификации и реализация механизмов повторного использования и модификации кода. Базовый класс задает общие признаки и общее поведение для классов-наследников.
Общие (наиболее общие) свойства и методы наследуются от базового класса, в дополнение к которым добавляются и определяются НОВЫЕ свойства и методы.
Таким образом, прежде всего наследование реализует механизмы расширения базового класса.
Реализация принципов наследования на примере:
using System; namespace Inheritance_1 { public class A { public int val1_A; public void fun1_A (String str) { Console.WriteLine("A's fun1_A:" + str); } } public class B:A { public int val1_B; public void fun1_B (String str) { Console.WriteLine("B's fun1_B:" + str); } } class Class1 { static void Main(string[] args) { B b0 = new B(); // От имени объекта b0 вызвана собственная функция fun1_B. b0.fun1_B("from B"); // От имени объекта b0 вызвана унаследованная от класса A функция fun1_A. b0.fun1_A("from B"); } } }
Наследование и проблемы доступа
Производный класс наследует от базового класса ВСЕ, что он имеет. Другое дело, что воспользоваться в производном классе можно не всем наследством.
Добавляем в базовый класс private -члены:
public class A { public int val1_A = 0; public void fun1_A (String str) { Console.WriteLine("A's fun1_A:" + str); this.fun2_A("private function from A:"); } // При определении переменных // в C# ничего не происходит без конструктора и оператора new. // Даже если они и не присутствуют явным образом в коде. private int val2_A = 0; private void fun2_A (String str) { Console.WriteLine(str + "A's fun2_A:" + val2_A.ToString()); } }
И объект-представитель класса B в принципе НЕ может получить доступ к private данным — членам и функциям — членам класса A. Косвенное влияние на такие данные-члены и функции — члены – лишь через public -функции класса A.
Следует иметь в виду еще одно важное обстоятельство.
Если упорядочить все (известные) спецификаторы доступа C# по степени их открытости
то наследуемый класс не может иметь более открытый спецификатор доступа, чем его предок.
Используем еще один спецификатор доступа – protected. Этот спецификатор обеспечивает открытый доступ к членам базового класса, но только для производного класса!
public class A { ::::::::: protected int val3_A = 0; } public class B:A { ::::::::: public void fun1_B (String str) { ::::::::: this.val3_A = 125; } } static void Main(string[] args) { ::::::::: //b0.val3_A = 125; // Это член класса закрыт для внешнего использования! }
Защищенные члены базового класса доступны для ВСЕХ прямых и косвенных наследников данного класса.
И еще несколько важных замечаний относительно использования спецификаторов доступа:
- в C# структуры НЕ поддерживают наследования. Поэтому спецификатор доступа protected в объявлении данных — членов и функций — членов структур НЕ ПРИМЕНЯЕТСЯ;
- спецификаторы доступа действуют и в рамках пространства имен (поэтому и классы в нашем пространстве имен были объявлены со спецификаторами доступа public ). Но в пространстве имен явным образом можно использовать лишь один спецификатор – спецификатор public, либо не использовать никаких спецификаторов.