Разделы презентаций


1 © Павловская Т.А. (СПбГУ ИТМО) Наследование

Содержание

©Павловская Т.А. (СПбГУ ИТМО)Возможности наследованияНаследование является мощнейшим инструментом ООП. Оно позволяет строить иерархии, в которых классы-потомки получают свойства классов-предков и могут дополнять их или изменять.Наследование применяется для следующих взаимосвязанных целей:исключения из

Слайды и текст этой презентации

Слайд 1©Павловская Т.А. (СПбГУ ИТМО)
Наследование

©Павловская Т.А. (СПбГУ ИТМО)Наследование

Слайд 2©Павловская Т.А. (СПбГУ ИТМО)
Возможности наследования
Наследование является мощнейшим инструментом ООП. Оно

позволяет строить иерархии, в которых классы-потомки получают свойства классов-предков и

могут дополнять их или изменять.
Наследование применяется для следующих взаимосвязанных целей:
исключения из программы повторяющихся фрагментов кода;
упрощения модификации программы;
упрощения создания новых программ на основе существующих.
Кроме того, наследование является единственной возможностью использовать классы, исходный код которых недоступен, но которые требуется использовать с изменениями.

©Павловская Т.А. (СПбГУ ИТМО)Возможности наследованияНаследование является мощнейшим инструментом ООП. Оно позволяет строить иерархии, в которых классы-потомки получают

Слайд 3©Павловская Т.А. (СПбГУ ИТМО)
Синтаксис
[ атрибуты ] [ спецификаторы ] class

имя_класса [ : предки ]
тело класса

class Monster
{ ... // кроме private и public,
// используется protected
}
class Daemon : Monster
{ ...
}
Класс в C# может иметь произвольное количество потомков
Класс может наследовать только от одного класса-предка и от произвольного количества интерфейсов.
При наследовании потомок получает [почти] все элементы предка.
Элементы private не доступны потомку непосредственно.
Элементы protected доступны только потомкам.


класс - только один
интерфейс - м.б. несколько

©Павловская Т.А. (СПбГУ ИТМО)Синтаксис[ атрибуты ] [ спецификаторы ] class имя_класса [ : предки ]  тело

Слайд 4©Павловская Т.А. (СПбГУ ИТМО)
Сквозной пример класса
class Monster {
public

Monster() // конструктор
{

this.name = "Noname";
this.health = 100;
this.ammo = 100;
}
public Monster( string name ) : this()
{ this.name = name; }
public Monster( int health, int ammo, string name )
{ this.name = name;
this.health = health;
this.ammo = ammo;
}
public int Health { // свойство
get { return health; }
set { if (value > 0) health = value;
else health = 0; }
}

public int Ammo { // свойство
get { return ammo; }
set { if (value > 0) ammo = value;
else ammo = 0; }
}
public string Name { // свойство
get { return name; }
}
public void Passport() // метод
{ Console.WriteLine(
"Monster {0} \t health = {1} \
ammo = {2}", name, health, ammo );
}
public override string ToString(){
string buf = string.Format(
"Monster {0} \t health = {1} \
ammo = {2}", name, health, ammo);
return buf; }
string name; // private поля
int health, ammo;
}


Слайд 5©Павловская Т.А. (СПбГУ ИТМО)
Daemon, наследник класса Monster
class Daemon : Monster

{
public Daemon() { brain = 1;

}

public Daemon( string name, int brain ) : base( name ) this.brain = brain; }

public Daemon( int health, int ammo, string name, int brain )
: base( health, ammo, name ) { this.brain = brain; }

new public void Passport() {
Console.WriteLine( "Daemon {0} \t health ={1} ammo ={2} brain ={3}",
Name, Health, Ammo, brain );
}
public void Think()
{ Console.Write( Name + " is" );
for ( int i = 0; i < brain; ++i )
Console.Write( " thinking" );
Console.WriteLine( "..." );
}

int brain; // закрытое поле
}

class Monster {
public Monster() // конструктор
{ this.name = "Noname";
this.health = 100; this.ammo = 100;
}
public Monster( string name ) : this()
{ this.name = name; }
public Monster( int health, int ammo, string name )
{ this.name = name;
this.health = health;
this.ammo = ammo; }

// в классе Monster было:
public void Passport() // метод
{
Console.WriteLine(
"Monster {0} \t health = {1} \
ammo = {2}",
name, health, ammo );
}

©Павловская Т.А. (СПбГУ ИТМО)Daemon, наследник класса Monsterclass Daemon : Monster {   public Daemon() {

Слайд 6©Павловская Т.А. (СПбГУ ИТМО)
Вызов конструктора базового класса
public Daemon( string name,

int brain ) : base( name )

// 1
{
this.brain = brain;
}

public Daemon( int health, int ammo, string name, int brain )
: base( health, ammo, name ) // 2
{
this.brain = brain;
}
©Павловская Т.А. (СПбГУ ИТМО)Вызов конструктора базового классаpublic Daemon( string name, int brain ) : base( name )

Слайд 7©Павловская Т.А. (СПбГУ ИТМО)
Конструкторы и наследование
Конструкторы не наследуются, поэтому производный

класс должен иметь собственные конструкторы (созданные программистом или системой).
Порядок

вызова конструкторов:
Если в конструкторе производного класса явный вызов конструктора базового класса отсутствует, автоматически вызывается конструктор базового класса без параметров.
Для иерархии, состоящей из нескольких уровней, конструкторы базовых классов вызываются, начиная с самого верхнего уровня. После этого выполняются конструкторы тех элементов класса, которые являются объектами, в порядке их объявления в классе, а затем исполняется конструктор класса.
Если конструктор базового класса требует указания параметров, он должен быть вызван явным образом в конструкторе производного класса в списке инициализации.
©Павловская Т.А. (СПбГУ ИТМО)Конструкторы и наследованиеКонструкторы не наследуются, поэтому производный класс должен иметь собственные конструкторы (созданные программистом

Слайд 8©Павловская Т.А. (СПбГУ ИТМО)
Наследование полей и методов
Поля, методы и свойства

класса наследуются.
При желании заменить элемент базового класса новым элементом следует

использовать ключевое слово new:
// метод класса Daemon (дополнение функций предка)
new public void Passport()
{
base.Passport(); // использование функций предка
Console.WriteLine( brain ); // дополнение
}

// метод класса Monster
public void Passport()
{
Console.WriteLine(
"Monster {0} \t health = {1} \
ammo = {2}",
name, health, ammo );
}

// метод класса Daemon (полная замена)
new public void Passport() {
Console.WriteLine( "Daemon {0} \ health ={1} ammo ={2} brain ={3}",
Name, Health, Ammo, brain );
}

©Павловская Т.А. (СПбГУ ИТМО)Наследование полей и методовПоля, методы и свойства класса наследуются.При желании заменить элемент базового класса

Слайд 9©Павловская Т.А. (СПбГУ ИТМО)
Совместимость типов при наследовании
Объекту базового класса можно

присвоить объект производного класса:

предок потомок
Это делается для единообразной работы со всей иерархией.

При преобразовании программы из исходного кода в исполняемый используется два механизма связывания:
раннее – early binding – до выполнения программы
позднее (динамическое) – late binding – во время выполнения
©Павловская Т.А. (СПбГУ ИТМО)Совместимость типов при наследованииОбъекту базового класса можно присвоить объект производного класса:

Слайд 10©Павловская Т.А. (СПбГУ ИТМО)
Пример раннего связывания
class T {
T(int

i) { this.i = i; }
draw

{ вывод "ТT" }
erase
move { erase, ->, draw }
number { вывод i }
protected int i;
}
class X : T {
X(int i) : base(i) {}
new draw {вывод "XX" }
new erase
resize
}
// все методы public

// одиночный объект:
X x = new X(15);
x.draw(); // XX
x.number(); // 15
x.move() // TT
// массив объектов баз. типа:
T mas = new T[n];
mas[0] = new T(10);
mas[1] = new T(20);
mas[2] = new X(15);
mas[3] = new X(25);

foreach (T t in mas) t.number()
// 10 20 15 25
foreach (T t in mas) t.draw()
// TT TT TT TT
// t.resize – не работает



Слайд 11©Павловская Т.А. (СПбГУ ИТМО)

Создание объекта x класса X

x.draw

x.number

x.move







Вызывающий метод

методы класса Т

Методы класса X

erase
draw
move
number
erase
draw
resize
Раннее связывание

©Павловская Т.А. (СПбГУ ИТМО)Создание объекта x класса X… x.draw x.number x.move Вызывающий методметоды класса ТМетоды класса Xerasedrawmovenumbererasedrawresize

Слайд 12©Павловская Т.А. (СПбГУ ИТМО)
Раннее связывание
Ссылки разрешаются до выполнения программы
Поэтому компилятор

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

свойство. То, что в этой переменной в разные моменты времени могут находиться ссылки на объекты разных типов, компилятор учесть не может.
Поэтому для ссылки базового типа, которой присвоен объект производного типа, можно вызвать только методы и свойства, определенные в базовом классе (т.е. возможность доступа к элементам класса определяется типом ссылки, а не типом объекта, на который она указывает).

Monster Vasia = new Daemon();
Vasia.Passport();

©Павловская Т.А. (СПбГУ ИТМО)Раннее связываниеСсылки разрешаются до выполнения программыПоэтому компилятор может руководствоваться только типом переменной, для которой

Слайд 13©Павловская Т.А. (СПбГУ ИТМО)
Позднее связывание
Происходит на этапе выполнения программы
Признак –

ключевое слово virtual в базовом классе:
virtual public void Passport() ...
Компилятор

формирует для virtual методов таблицу виртуальных методов. В нее записываются адреса виртуальных методов (в том числе унаследованных) в порядке описания в классе.
Для каждого класса создается одна таблица.
Связь с таблицей устанавливается при создании объекта с помощью кода, автоматически помещаемого компилятором в конструктор объекта.
Если в производном классе требуется переопределить виртуальный метод, используется ключевое слово override:
override public void Passport() ...
Переопределенный виртуальный метод должен обладать таким же набором параметров, как и одноименный метод базового класса.
©Павловская Т.А. (СПбГУ ИТМО)Позднее связываниеПроисходит на этапе выполнения программыПризнак – ключевое слово virtual в базовом классе:virtual public

Слайд 14©Павловская Т.А. (СПбГУ ИТМО)
Пример позднего связывания
class T {
T(int

i)
virtual draw { "ТT" }
virtual erase
move { erase,

…, draw }
number { i }
protected int i;
}
class X : T {
X(int i)
override draw { "XX" }
override erase
resize
}

// все методы public

// одиночный объект:
X x = new X(15);
x.draw(); // XX
x.number(); // 15
x.move() // XX
// массив объектов баз. типа:
T mas = new T[n];
mas[0] = new T(10);
mas[1] = new T(20);
mas[2] = new X(15);
mas[3] = new X(25);

foreach (T t in mas) t.number()
// 10 20 15 25
foreach (T t in mas) t.draw()
// TT TT XX XX

©Павловская Т.А. (СПбГУ ИТМО)Пример позднего связыванияclass T {	  T(int i)virtual draw {

Слайд 15©Павловская Т.А. (СПбГУ ИТМО)

Создание объекта x класса X

x.draw

x.number

x.move

t.move







Вызывающий метод

методы класса Т

Методы класса X

erase
draw
move
number
resize
Позднее связывание
адрес

erase

адрес draw

адрес erase

адрес draw

VMT для X

VMT для T

Виртуальные методы T

Виртуальные методы X

draw

erase

©Павловская Т.А. (СПбГУ ИТМО)Создание объекта x класса X… x.draw x.number x.move t.move Вызывающий методметоды класса ТМетоды класса

Слайд 16©Павловская Т.А. (СПбГУ ИТМО)
Полиморфизм
Виртуальные методы базового класса определяют интерфейс всей

иерархии.
Интерфейс может расширяться в потомках за счет добавления новых

виртуальных методов (нежелательно).
Переопределять виртуальный метод в каждом из потомков не обязательно: если он выполняет устраивающие потомка действия, метод наследуется.
Механизм вызова виртуального метода:
из объекта берется адрес таблицы вирт. методов соотв. класса
из нее выбирается адрес метода
ему передается управление.
Итак, при использовании виртуальных методов из всех одноименных методов иерархии всегда выбирается тот, который соответствует фактическому типу вызвавшего его объекта.
Виртуальные методы  — основное проявление полиморфизма.

Monster Vasia = new Daemon();
Vasia.Passport();

©Павловская Т.А. (СПбГУ ИТМО)ПолиморфизмВиртуальные методы базового класса определяют интерфейс всей иерархии. Интерфейс может расширяться в потомках за

Слайд 17©Павловская Т.А. (СПбГУ ИТМО)
Применение виртуальных методов
Виртуальные методы используются:
при работе с

производными классами через ссылку на базовый класс;
при передаче объектов в

методы в качестве параметров:
В параметрах метода описывается объект базового типа, а при вызове в нее передается объект производного класса. Виртуальные методы, вызываемые для параметра метода, будут соответствовать типу аргумента, а не параметра.
Методы, работающие с полиморфными объектами, называют полиморфными.
©Павловская Т.А. (СПбГУ ИТМО)Применение виртуальных методовВиртуальные методы используются:при работе с производными классами через ссылку на базовый класс;при

Слайд 18©Павловская Т.А. (СПбГУ ИТМО)
Пример полиморфного метода
Т - предок
Х - потомок
в

обоих классах есть виртуальный метод draw
T t = new T(10);
X

x = new X(20);
КакойтоМетод( t )  вызывается draw из Т
КакойтоМетод( x )  вызывается draw из X

КакойтоМетод ( Т t )
{
t.draw(); …
}

©Павловская Т.А. (СПбГУ ИТМО)Пример полиморфного методаТ - предокХ - потомокв обоих классах есть виртуальный метод drawT t

Слайд 19©Павловская Т.А. (СПбГУ ИТМО)
При описании классов рекомендуется определять в качестве

виртуальных те методы, которые в производных классах должны реализовываться по-другому.


Если во всех классах иерархии метод будет выполняться одинаково, его лучше определить как обычный метод.

©Павловская Т.А. (СПбГУ ИТМО)При описании классов рекомендуется определять в качестве виртуальных те методы, которые в производных классах

Обратная связь

Если не удалось найти и скачать доклад-презентацию, Вы можете заказать его на нашем сайте. Мы постараемся найти нужный Вам материал и отправим по электронной почте. Не стесняйтесь обращаться к нам, если у вас возникли вопросы или пожелания:

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика