Наследование. Полиморфизм.

advertisement
Наследование и
полиморфизм.
«Быть» или «Иметь»
а так же
«Точно» или «Как получится»
Наследование = расширение
возможностей.
В чём разница?
 «Быть - классическое
 «Иметь – включение-
наследование, 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.
Сокрытие методов.
Запрет наследования логики базовых
версий.
Вызов варианта базового класса с помощью
явного приведения типа.
Используется при межъязыковом
наследовании, например.
Приведение типов.
 Если один класс является
производным от другого, то всегда
безопасно ссылаться на объект
производного класса через объект
базового класса.
…
Download
Study collections