1. Понятие позднего и раннего связывания. Ключевые слова virtual, override


Пример. Заданы 2 класса с именами Base


Download 0.51 Mb.
bet4/17
Sana01.09.2023
Hajmi0.51 Mb.
#1672075
1   2   3   4   5   6   7   8   9   ...   17
Bog'liq
C# да ПОЛИМОРФИЗМ ва ИНТЕРФЕЙСЛАР

Пример.
Заданы 2 класса с именами Base и Derived. Класс Derived наследует класс Base. В обоих классах определен виртуальный метод Info(), который выводит информацию о классе. Вызов виртуального метода Info() осуществляется из статического метода ShowInfo() класса Program. Метод ShowInfo() получает входным параметром ссылку на базовый класс и по этой ссылке обращается к методу Info() класса. В зависимости от того, экземпляр какого класса передается в метод ShowInfo(), соответствующий метод Info() вызывается.
using System;
namespace ConsoleApp5
{
// Передача в метод ссылки на базовый класс
class Base
{
// Виртуальный метод Info()
public virtual void Info()
{
Console.WriteLine("Base.Info()");
}
}


class Derived : Base
{
// Виртуальный метод Info() унаследованного класса
public override void Info()
{
Console.WriteLine("Derived.Info()");
}
}


class Program
{
// Статический метод ShowInfo() - получает ссылку
// на базовый класс Base в качестве параметра
static void ShowInfo(Base r)
{
// Вызов метода Info() по ссылке.
// В этом методы неизвестно, на экземпляр какого класса
// указывает r: на Base или на Derived?
// Компилятор сгенерирует код на этапе выполнения - этот процесс
// называется поздним связыванием.
r.Info(); // единый интерфейс (вызов) для всех реализаций экземпляров
}


static void Main(string[] args)
{
// Демонстрация полиморфизма и позднего связывания
// 1. Объявить ссылку на базовый класс
Base rB;


// 2. Создать экземпляры классов Base и Derived
Base oB = new Base();
Derived oD = new Derived();


// 3. Вызов метода ShowInfo() с передачей параметра rB,
// который указывает на экземпляр oB класса Base
rB = oB;
ShowInfo(rB); // вызывается Base.Info()

rB = oD;
ShowInfo(rB); // вызывается Derived.Info()




// 4. Вызова метода ShowInfo(), в метод передаются
// объекты oB и oD
ShowInfo(oB); // вызывается Base.Info()
ShowInfo(oD); // вызывается Derived.Info()


// Вывод: метод ShowInfo() на этапе компиляции не знает,
// экземпляр какого класса ему будет передан в качестве параметра.
// Метод ShowInfo() реализует единообразный вызов метода
// Info: r.Info() для всех экземпляров, что ему будут переданы -
// это называется "один интерфейс".
}
}
}


6. Какие требования накладываются на элемент класса для того, чтобы он поддерживал полиморфизм?

Для того, чтобы элемент класса (например метод) поддерживал полиморфизм, его нужно сделать виртуальным. Чтобы элемент класса был виртуальным, нужно выполнить следующие требования:

  • в базовом классе этот элемент (метод, свойство) должен быть обозначен как virtual или abstract. Ключевое слово abstract также делает элемент виртуальным. Это слово используется, если элемент класса есть абстрактным. Более подробно об абстрактных классах описывается здесь;

  • в производных классах одноименные элементы должны быть обозначены как override. Если в производном классе нужно реализовать невиртуальный метод, имя которого совпадает с виртуальным методом базового класса, то этот метод обозначается ключевым словом new (смотрите пункт 7).

7. Использование ключевого слова new в цепочке виртуальных методов. Пример

Как известно, элемент класса, который объявлен виртуальным (virtual), передает возможность реализовать полиморфизм в одноименных элементах унаследованных классов. Таким образом, виртуальные элементы образовывают цепочку вниз по иерархии.
Для того, чтобы элемент класса, который переопределяет (override) виртуальный элемент базового класса, не поддерживал полиморфизм нужно указать ключевое слово new. Если в цепочке одноименных виртуальных методов встречается один невиртуальный метод (с ключевым словом new) то этот метод разрывает цепочку.
Пример. Заданы классы с именами A1, A2, A3, A4. Классы образовывают иерархию наследования. В классе A3 объявляется метод Print() с ключевым словом new, разрывающий цепочку виртуальных методов.
Текст демонстрационной программы следующий
using static System.Console;
namespace ConsoleApp5
{
// Базовый класс в иерархии
class A1
{
// Виртуальный метод Print()
virtual public void Print()
{
WriteLine("A1.Print()");
}
}


// Класс, производный от класса A1
class A2 : A1
{
// виртуальный метод Print()
override public void Print()
{
WriteLine("A2.Print()");
}
}


// Класс, производный от класса A2
class A3 : A2
{
// Невиртуальный метод Print() - данный метод
// разрывает цепочку виртуальных методов,
// метод обозначен ключевым словом new
new public void Print()
{
WriteLine("A3.Print()");
}
}


// Класс, производный от класса A3
class A4 : A3
{
// Опять невиртуальный метод Print().
// Установить здесь ключевое слово override не выйдет,
// потому что цепочка виртуальных методов разорвана.
new public void Print() // только new можно использовать
{
WriteLine("A4.Print()");
}
}


class Program
{
static void Main(string[] args)
{
// 1. Ссылка на базовый класс
A1 refA1;


// 2. Экземпляры классов
A1 objA1 = new A1();
A2 objA2 = new A2();
A3 objA3 = new A3();
A4 objA4 = new A4();


// 3. Вызов метода Print() экземпляров
// A1, A2, A3, A4 через ссылку refA1
refA1 = objA1;
refA1.Print(); // A1.Print - метод базового класса


// objA2
refA1 = objA2;
refA1.Print(); // A2.Print - полиморфизм


// objA3
refA1 = objA3;
refA1.Print(); // A2.Print - нету полиморфизма
(refA1 as A3).Print(); // A3.Print - статический полиморфизм


// objA4
refA1 = objA4;
refA1.Print(); // A2.Print - нету полиморфизма
(refA1 as A4).Print(); // A4.Print - статический полиморфизм
}
}
}
На рисунке 4 схематично изображен вызов метода Print() в случае использования ключевого слова new.
Рисунок 4. Иерархия классов A1, A2, A3, A4. Разрыв цепи виртуальных методов Print() в классе A3
Результат работы программы
A1.Print()
A2.Print()
A2.Print()
A3.Print()
A2.Print()
A4.Print()


8. Пример классов Figure->Rectangle->RectangleColor, демонстрирующих полиморфизм

Объявить класс Figure, содержащий поле name, которое определяет название фигуры. В классе Figure объявить следующие методы:

  • конструктор с 1 параметром;

  • метод Display(), отображающий название фигуры.

Из класса Figure унаследовать класс Rectangle (прямоугольник), который содержит следующие поля:

  • координату левого верхнего угла (x1; y1);

  • координату правого нижнего угла (x2; y2).

В классе Rectangle реализовать следующие методы и функции:

  • конструктор с 5 параметрами, который вызывает конструктор базового класса Figure;

  • конструктор без параметров, который реализует установку координат углов (0; 0), (1; 1) и вызывает конструктор с 5 параметрами с помощью средства this;

  • метод Display(), отображающий название фигуры и значения внутренних полей. Данный метод обращается к одноименному методу базового класса;

  • метод Area(), возвращающий площадь прямоугольника.

Из класса Rectangle унаследовать класс RectangleColor. В классе RectangleColor реализовать поле color (цвет) и следующие методы;

  • конструктор с 6 параметрами, который вызывает конструктор базового класса Rectangle;

  • конструктор без параметров, который устанавливает координаты (0; 0), (1; 1) и вызывает конструктор с 6 параметрами с помощью средства this;

  • метод Display(), отображающий название фигуры и значения внутренних полей. Данный метод обращается к одноименному методу базового класса;

  • метод Area(), возвращающий площадь прямоугольника. В методе вызывается метод Area() базового класса.




Download 0.51 Mb.

Do'stlaringiz bilan baham:
1   2   3   4   5   6   7   8   9   ...   17




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©fayllar.org 2024
ma'muriyatiga murojaat qiling