Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
7 семестр / Учебники / Все лекции С# / Все лекции С# / Лекция 15. Наследование. Виртуальные функции.Переопределение.doc
Скачиваний:
146
Добавлен:
24.02.2016
Размер:
64.51 Кб
Скачать

Синтаксис объявления наследования

publicclassmybase

{ … }

public class derived: mybase //НАСЛЕДОВАНИЕ

{ …}

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

Механизм виртуальных функций – одна из реализаций основной концепций ООП – полиморфизма. Данный механизм предполагает использование идеи «один интерфейс-множество методов реализации». Эта идея заключается в том, что базовый класс обеспечивает для производных классов все элементы, которые эти классы могут использовать непосредственно, а также содержит набор функций, которые производные классы должны реализовать путем их переопределения (создание собственного кода функции в производном классе, путем сокрытия или замещения кода базовой реализации).

Виртуальный метод– это функция, объявленная с ключевым словомvirtual в базовом классе и переопределенная в одном или нескольких производных от этого классах. Обязательное требование: заголовок функции должен быть точно такой же, как в базовом классе. Тогда при создании объекта или базового, или любого из производных классов компилятор определяет, какую из функций требуется вызвать, основываясь на типе объекта.

Правила использования виртуальных методов

1.Если функция виртуалъная в некотором классе, то она останется виртуальной в не зависимости от уровня иерархии.

2.Если в производном классе виртуальная функция не переопределяется, то используется ее версия из базового класса.

3.ВиртуалЬные функции должны иметь один интерфейс по всей иерархии класса.

Полиморфизм– способность объектов различных классов связанных между собой наследованием различным образом реагировать на вызов одной и той же функции.

Сокрытие методов базового класса

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

publicclassmybase

{

publicvoidf() { //базовая реализация}

}

public class derived: mybase

{

publicvoidf() { //реализация, скрывающая базовую реализацию}

}

Хотя такой код будет работать нормально, он сгенерирует предупреждение о том, что в нем скрывается член базового класса. Это дает возможность исправить положение дел, если мы случайно скрыли член, который на самом деле желаем использовать. Если же этот член действительно требуется скрыть, то об этом можно сказать явно, воспользовавшись ключевым словомnew:

publicclassderived:mybase

{

new publicvoidf() {//теперь ДЕЙСТВИТЕЛЬНО скрыли базовую реализацию}

}

Этот код будет работать точно так же, только без выдачи предупреждения.

Разницу между скрытыми и переопределенными членами базового класса рассмотрим на примере:

public class mybase

{

public virtual void f() { Console.WriteLine("Базовая реализация");}

}

public class derived: mybase

{

public override void f() { Console.WriteLine('Производная реализация");}

}

В данном случае переопределенный метод f()заменяет собойреализацию базового класса, так что в следующем коде будет использоваться новая версия, несмотря на то, что обращение к методу происходит через тип базового класса (с использованием полиморфизма):

derived d= new derived();

mybase b;

b=d; //обратите внимание на присвоение экземпляров классов

b.f();

Результатом объявления экземпляров базового и производного классов и вызова переопределенного метода f() будет следующее:Производная реализация

В качестве альтернативы можно скрыть метод базового класса с помощью следующего кода:

public class mybase

{

public virtual void f() { Console.WriteLine('Базовая реализация");}

}

public class derived : mybase

{ new public void f() {Console.WriteLine("Производная реализация") ;}

}

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

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