Объектно-ориентированное программирование. Наследование

Содержание

Слайд 2

Наследование Насле́дование — механизм объектно-ориентированного программирования, позволяющий описать новый класс на

Наследование

Насле́дование — механизм объектно-ориентированного программирования, позволяющий описать новый класс на основе

уже существующего (родительского), при этом свойства и функциональность родительского класса заимствуются новым классом.
Слайд 3

Наследование

Наследование

Слайд 4

Наследование

Наследование

Слайд 5

Наследование

Наследование

Слайд 6

Наследование Класс, от которого произошло наследование, называется базовым или родительским (base

Наследование

Класс, от которого произошло наследование, называется базовым или родительским (base class).

Классы, которые произошли от базового, называются потомками, наследниками, подклассами или производными классами (derived class).
Слайд 7

Наследование

Наследование

Слайд 8

Наследование При наследовании все атрибуты и методы родительского класса наследуются классом-потомком.

Наследование

При наследовании все атрибуты и методы родительского класса наследуются классом-потомком.
Наследование

может быть многоуровневым, и тогда классы, находящиеся на нижних уровнях иерархии, унаследуют все свойства (атрибуты и методы) всех классов, прямыми или косвенными потомками которых они являются.
Класс B унаследует атрибуты и методы класса A и, следовательно, будет обладать атрибутами A, B, C и D и методами A, B, C и D, а класс C – атрибутами A, B, C, E, F и методами A, B и E. 
Слайд 9

Наследование Помимо единичного, существует и множественное наследование, когда класс наследует сразу

Наследование

Помимо единичного, существует и множественное наследование, когда класс наследует сразу нескольким

классам. При этом он унаследует свойства всех классов, потомком которых он является.
При использовании множественного наследования необходимо быть особенно внимательным, так как возможны коллизии, когда класс-потомок может унаследовать одноименные свойства, с различным содержанием.
 С# не поддерживает множественное наследование.
Слайд 10

Наследование При наследовании одни методы класса могут замещаться другими. Так, класс

Наследование

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

средств будет обладать обобщенным методом движения. В классах-потомках этот метод будет конкретизирован: автомобиль будет ездить, самолет – летать, корабль – плавать. Такое изменение семантики метода называется полиморфизмом.
Полиморфи́зм — возможность объектов с одинаковой спецификацией иметь различную реализацию. (Один интерфейс, множество реализаций) 
Слайд 11

Наследование class имя_наследника: имя_базового_класса {тело класса} Наследник обладает всеми полями, методами

Наследование

class имя_наследника: имя_базового_класса
{тело класса}
Наследник обладает всеми полями, методами и свойствами

предка, однако элементы предка с модификатором private не доступны в наследнике.
При наследовании нельзя расширить область видимости класса: internal–класс может наследоваться от public–класса, но не наоборот
Слайд 12

Наследование Ничего не делающий самостоятельно потомок не эффективен, от него мало

Наследование

Ничего не делающий самостоятельно потомок не эффективен, от него мало проку.

Что же может делать потомок?
Прежде всего, он может добавить новые свойства - поля класса.
Заметьте, потомок не может ни отменить, ни изменить модификаторы или типы полей, наследованных от родителя - он может только добавить собственные поля.
Слайд 13

класс "Питомец" class CPet { public int eyes = 2; //глаза

класс "Питомец"

class CPet
{
public int eyes = 2; //глаза
public

int tail; // хвост
public int legs; // ноги
public CPet()
{
tail = 1;
}
public void Speak()
{
Console.WriteLine("I'm a pet");
}
}
Слайд 14

класс "Питомец" Это общий класс. В нем могут быть все виды

класс "Питомец"

Это общий класс.
В нем могут быть все виды питомцев

(собаки, птички, рыбки).
У всех 2 глаза, 1 хвост и какое-то к-во ног. Все могут говорить.
Слайд 15

Наследование CPet Pet = new CPet(); Console.WriteLine("Pet.eyes = "+ Pet.eyes); Console.WriteLine("Pet.tail

Наследование

CPet Pet = new CPet();
Console.WriteLine("Pet.eyes = "+ Pet.eyes);
Console.WriteLine("Pet.tail = "+ Pet.tail);
Console.WriteLine("Pet.legs

= "+ Pet.legs);
Pet.Speak();
Слайд 16

Создадим наследников class CDog : CPet { public CDog() { legs

Создадим наследников

class CDog : CPet
{
public CDog()
{
legs = 4;
}
}
class CBird :

CPet
{
public int wings = 2;
}
Слайд 17

Наследование CDog Dog = new CDog(); Console.WriteLine("Dog.eyes = "+ Dog.eyes); Console.WriteLine("Dog.tail

Наследование

CDog Dog = new CDog();
Console.WriteLine("Dog.eyes = "+ Dog.eyes);
Console.WriteLine("Dog.tail = "+ Dog.tail);
Console.WriteLine("Dog.legs

= "+ Dog.legs);
Dog.Speak();
CBird Bird = new CBird();
Console.WriteLine("Bird.eyes = "+ Bird.eyes);
Console.WriteLine("Bird.tail = "+ Bird.tail);
Console.WriteLine("Bird.legs = "+ Bird.legs);
Console.WriteLine("Bird.wings = " + Bird.wings);
Bird.Speak();
Слайд 18

Наследование Собаки имеют свой конструктор с к-вом ног = 4. У

Наследование

Собаки имеют свой конструктор с к-вом ног = 4. У птиц

появилось новое поле – крылья.
Все пока говорят одно и тоже.
Обратите внимание, что родительский конструктор сработал во всех случаях (это хвост).
Слайд 19

Наследование Все члены родительского класса public. Давайте попробуем сделать скрытыми глаза: int eyes = 2; //глаза

Наследование

Все члены родительского класса public.
Давайте попробуем сделать скрытыми глаза:
int eyes

= 2; //глаза
Слайд 20

Наследование То, что появятся ошибки при выводе, понятно. (закомментируем). Но как

Наследование

То, что появятся ошибки при выводе, понятно. (закомментируем). Но как быть

с наследниками? Наследники должны видеть члены родительского класса.
Слайд 21

Наследование Давайте заведем одноглазую собаку. private скрывает и от наследников.

Наследование

Давайте заведем одноглазую собаку.
private скрывает и от наследников.

Слайд 22

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

Наследование

Напомню, хорошей стратегией является стратегия "ничего не скрывать от потомков". Какой

родитель знает, что именно из сделанного им может понадобиться потомкам?
Для этого существует protected.
Слайд 23

Наследование

Наследование

Слайд 24

Добавим свои слова собаке class CDog : CPet { public CDog()

Добавим свои слова собаке

class CDog : CPet
{
public CDog()

{
legs = 4;
eyes = 1; // нет ошибки
}
public void Speak()
{
Console.WriteLine("I'm a dog");
}
}
Слайд 25

Наследование Теперь команда Dog.Speak(); даст результат:

Наследование

Теперь команда
Dog.Speak();
даст результат:

Слайд 26

Наследование Но такая грубая перегрузка метода вызовет предупреждение.

Наследование

Но такая грубая перегрузка метода вызовет предупреждение.

Слайд 27

Наследование Для явного указания компилятору, что мы знаем, что делаем, используется

Наследование

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

new.
new public void Speak()
{
Console.WriteLine("I'm a dog");
}
Такой способ называется скрытием метода.
Слайд 28

Наследование Класс-наследник может иметь собственных наследников. class CMutant : CDog {

Наследование

Класс-наследник может иметь собственных наследников.
class CMutant : CDog
{
public CMutant()
{

legs = 5;
}
new public void Speak()
{
Console.WriteLine("I'm a mutant");
}
}
Слайд 29

Наследование CMutant Mutant = new CMutant(); Console.WriteLine("Mutant.eyes = " + Mutant.eyes);

Наследование

CMutant Mutant = new CMutant();
Console.WriteLine("Mutant.eyes = " + Mutant.eyes);
Console.WriteLine("Mutant.tail = "

+ Mutant.tail);
Console.WriteLine("Mutant.legs = " + Mutant.legs);
Mutant.Speak();
Слайд 30

Наследование Но при этом она еще помнит, что она собака. Метод

Наследование

Но при этом она еще помнит, что она собака. Метод Speak

вызывает метод Speak родительского класса (который был скрыт):
Слайд 31

Наследование class CMutant : CDog { public CMutant() { legs =

Наследование

class CMutant : CDog
{
public CMutant()
{
legs = 5;
}

new public void Speak()
{
base.Speak();
Console.WriteLine("I'm a mutant");
}
}
Слайд 32

Наследование Для этого используется ключевое слово base. Кстати, для обращения к

Наследование

Для этого используется ключевое слово base. Кстати, для обращения к собственному

объекту, если это необходимо, используется слово this.
Слайд 33

Наследование Обратите внимание, как здесь сработали конструкторы: сначала был вызван конструктор

Наследование

Обратите внимание, как здесь сработали конструкторы: сначала был вызван конструктор самого

первого предка (CPet). Один хвост задавался именно там. Потом сработал конструктор его потомка: CDog. 4 ноги и 1 глаз. И уже в последнюю очередь – собственный конструктор CMutant – ног стало 5.
Слайд 34

Наследование Каждый класс должен позаботиться о создании собственных конструкторов. Он не

Наследование

Каждый класс должен позаботиться о создании собственных конструкторов.
Он не может

в этом вопросе полагаться на родителя, поскольку, как правило, добавляет собственные поля, о которых родитель ничего не может знать.
Каждый конструктор класса-потомка вызывает сначала родительский конструктор.
Если для вызова конструктора требуются аргументы, родительский конструктор нужно вызывать явно.
Слайд 35

Класс "Рыбка" class CFish : CPet { public int fins; //

Класс "Рыбка"

class CFish : CPet
{
public int fins; // плавник
public

CFish(int eyes, int tail, int fins)
{
this.eyes = eyes;
this.tail = tail;
this.fins = fins;
}
}
Слайд 36

Класс "Акула" class CShark : CFish { public int teeth; //

Класс "Акула"

class CShark : CFish
{
public int teeth; // зубы
public CShark(int

eyes, int tail, int fins, int teeth)
: base(eyes, tail, fins)
{
this.teeth = teeth;
}
}
Слайд 37

Наследование CShark Shark = new CShark(2, 1, 4, 100); Console.WriteLine("Shark.eyes =

Наследование

CShark Shark = new CShark(2, 1, 4, 100);
Console.WriteLine("Shark.eyes = " +

Shark.eyes);
Console.WriteLine("Shark.tail = " + Shark.tail);
Console.WriteLine("Shark.legs = " + Shark.fins);
Console.WriteLine("Shark.teeth = " + Shark.teeth);
Shark.Speak();