Наследование и полиморфизм. «Быть» или «Иметь» а так же «Точно» или «Как получится» Наследование = расширение возможностей. В чём разница? «Быть - классическое «Иметь – включение- наследование, is a» делегирование, has a» Каждый производный класс расширяет возможности базового. Класс объявляется внутри другого, который разрешает с помощью своих методов использовать возможности вложенного Полиморфизм. Одинаковый интерфейс – разные действия. Классический. public class Target : Object { public virtual void SelfDestruction() {…} } public class AirTarget : Target { public override void SelfDestruction() {…} } Target t = new Target(); AirTarget at = new AirTarget(); t.SelfDestruction(); at.SelfDestruction(); Полиморфизм для конкретного случая («ad-hoc», «позднее связывание – определение вызываемого метода в ходе выполнения»). Target a1 = new AirTarget(), a2 = new Airship(); a1.SelfDestruction(); a2.SelfDestruction(); Тип объекта может определяться динамически, соответственно «на ходу» определяется вызываемый метод. А теперь подробнее… Наследование.Классическое Базовые классы определяют общую функциональность всех производных. Производные классы расширяют функциональность за счёт своих методов. Наследуются только открытые методы. Указатель на базовый класс выглядит как «:» - и при определении производного, и при обращении к конструктору базового в производном. Множественное наследование невозможно!!! public class A { public A(A_Params) {…} } public class B : A { public B(B_params) : base (A_Params) {…} } public Manager(string Name,int ID,int Section ) : base (Name, ID) { … } Семейные тайны и запреты. Можно запретить внешний вызов метода, объявив его как protected. При этом он будет считаться видимым для всех наследуемых, но недоступным извне. Можно вообще запретить наследование, объявив класс как sealed. Например, для запрета наследования за пределами сборки. public sealed class LostClass : SomeClass { … } Модель включенияделегирования. Класс-контейнер – родительский. Внутренний класс – дочерний. Ответственность за жизнеспособность внутреннего класса несёт внешний. Делегирование «полномочий». Пользователь может и не подозревать о существовании внутреннего класса, вызывая методы «опекуна». Как это происходит… Само наследование: public class Car { … private Radio musicBox; public Car () { musicBox = new Radio(); } } Или public class Car { … private Radio = new musicBox(); }; Делегирование public class Car { … public void TurnOnRadio() { … musicBox.TurnOn(); } } И ещё – вложенные (nested) классы. Исключительно вспомогательные функции. Невозможно обращение извне. Строгий контроль области видимости. Почти то же самое, что модель включения-делегирования. Можно вкладывать классы, интерфейсы и структуры. public class Car { … private class Radio { public Radio() { … } public void TurnOn() { … } } private Radio musicBox; public void TurnOnRadio() { musicBox.TurnOn(); } } Полиморфизм («не совсем» перегрузка!). Задача – заставить один и тот же метод (метод с одинаковым прототипом) поразному реагировать на объекты разных классов. В замещённых версиях методов, как правило, расширяется функциональность метода базового класса. Метод базового класса, который должен быть замещён в производном, объявляется как virtual. Метод производного класса, который должен замещать виртуальный метод базового класса, должен быть объявлен как override. public class Target { ... public virtual void Selfdestruction() { ... } } public class AirTarger : Target { ... public override void SelfDestruction() { base.SelfDestruction(); ... } } Это далеко не всё! Абстрактные классы – запрет на создание объектов «самого базового» класса. Принудительный полиморфизм – абстрактные методы. Контроль версий членов класса (versioning). Приведение типов. Абстрактные классы. Абстрактные классы позволяют запретить создание объектов некоторого класса. abstract public class MainBaseClass { … } Не обязательно наличие чисто виртуальных методов. Абстрактные (чисто виртуальные) методы Только в абстрактных классах. Обязательно должны быть замещены. Незамещённые виртуальные методы будут вызваны из базовой версии. Чтобы объявить метод абстрактным, достаточно не указывать его реализацию. Незамещённый абстрактный метод таким и останется в производном классе, со всеми вытекающими последствиями. Вся мощь полиморфизма public abstract class Target {… public virtual void SelfDestruction(); } public class AirTarget : Target {… public override void SelfDestruction() {…} } public class LandTarget : Target {-”-} public class SeaTarget : Target {-”-} public class MainClass {… public static int Main (string[] args) {… Target[] targets = {new AirTarget(), new Landtarget(), new SeaTarget()}; for (int i=0;i<targets.Lenght;i++) targets[i].SelfDestruction(); } } Контроль версий членов классов. Разрыв отношений на уровне одного метода – достаточно объявить метод как new. Сокрытие методов. Запрет наследования логики базовых версий. Вызов варианта базового класса с помощью явного приведения типа. Используется при межъязыковом наследовании, например. Приведение типов. Если один класс является производным от другого, то всегда безопасно ссылаться на объект производного класса через объект базового класса. …