Студопедия

Главная страница Случайная страница

КАТЕГОРИИ:

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Три механизма, обеспечивающие полиморфизм






Под полиморфизмом в ООП понимают способность одного и того же программного текста

x1.M(arg1, arg2, … argN);

выполняться по-разному, в зависимости от того, с каким объектом связана сущность x. Полиморфизм гарантирует, что вызываемый метод M будет принадлежать классу объекта, связанному с сущностью x. В основе полиморфизма, характерного для семейства классов, лежат три механизма.

  • Одностороннее присваивание объектов внутри семейства классов. Сущность, базовым классом которой является класс предка, можно связать с объектом любого из потомков. Другими словами, для введенной нами последовательности объектовxk присваивание xi = xj допустимо для всех j > =i.
  • Переопределение потомком метода, наследованного от родителя. Благодаря переопределению в семействе классов существует совокупность полиморфных методов с одинаковым именем и одинаковой сигнатурой, но разной реализацией.
  • Динамическое связывание, позволяющее в момент выполнения вызывать метод, принадлежащий объекту, с которым связана сущность в момент вызова.

В совокупности это и называется полиморфизмом семейства классов. Целевую сущность часто называют полиморфной сущностью, вызываемый метод - полиморфным методом, сам вызов - полиморфным вызовом.

class Font

{

string TypeFont;

short FontSize;

 

public Font()

{

TypeFont = " Arial";

FontSize = 12;

}

 

public Font(string TypeFont, short FontSize)

{

this.TypeFont = TypeFont;

this.FontSize = FontSize;

}

 

public string typeFont

{

get

{

return TypeFont;

}

 

set

{

TypeFont = value;

}

}

 

public short fontSize

{

get

{

return FontSize;

}

 

set

{

FontSize = value;

}

}

 

// Создаем виртуальный метод

public virtual string FontInfo(Font obj)

{

string s = " Информация о шрифте: \n------------------\n\n" +

" Тип шрифта: " + typeFont +

" \nРазмер шрифта: " + fontSize + " \n";

return s;

}

}

 

// Производный класс 1 уровня

class ColorFont: Font

{

byte Color;

 

public ColorFont(byte Color, string TypeFont, short FontSize)

: base(TypeFont, FontSize)

{

this.Color = Color;

}

 

// Переопределение для виртуального метода

public override string FontInfo(Font obj)

{

// Используется ссылка на метод определенный в базовом классе Font

return base.FontInfo(obj) + " Цвет шрифта: " + Color + " \n";

}

 

// Создадим виртуальное свойство

public virtual byte color

{

set

{

Color = value;

}

 

get

{

return Color;

}

}

}

 

// Производный класс 2 уровня

class GradientColorFont: ColorFont

{

char TypeGradient;

 

public GradientColorFont(char TypeGradient, byte Color, string TypeFont, short FontSize):

base(Color, TypeFont, FontSize)

{

this.TypeGradient = TypeGradient;

}

 

// Опять переопределяем виртуальный метод

public override string FontInfo(Font obj)

{

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

return base.FontInfo(obj) + " Тип градиента: " + TypeGradient + " \n\n";

}

 

// Переопределим виртуальное свойство

public override byte color

{

get

{

return base.color;

}

set

{

if (value < 10)

base.color = 0;

else

base.color = (byte)(value - 0x0A);

}

}

}

 

// Еще один производный класс 1 уровня

class FontStyle: Font

{

string style;

 

public FontStyle(string style, string TypeFont, short FontSize): base (TypeFont, FontSize)

{

this.style = style;

}

 

// Данный метод не переопределяет виртуальный метод

// поэтому при вызове метода FontInfo ()

// вызывыется метод созданный в базовом классе

}

 

class Program

{

static void Main()

{

ColorFont font1 = new ColorFont(Color: 0xCF, TypeFont: " MS Trebuchet", FontSize: 16);

Console.WriteLine(font1.FontInfo(font1));

 

GradientColorFont font2 = new GradientColorFont(Color: 0xFF, TypeFont: " Times New Roman", FontSize: 10, TypeGradient: 'R');

Console.WriteLine(font2.FontInfo(font2));

 

font2.color = 0x2F;

Console.ForegroundColor = ConsoleColor.Green;

Console.WriteLine(" Видоизмененный цвет font2");

Console.ForegroundColor = ConsoleColor.Gray;

Console.WriteLine(font2.FontInfo(font2));

 

FontStyle font3 = new FontStyle(style: " oblique", TypeFont: " Calibri", FontSize: 16);

Console.WriteLine(font3.FontInfo(font3));

 

Console.ReadLine();

}

}

 

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

class A1

{

public virtual void Virt()

{

Console.WriteLine(" This is a virtual method of {0}", this.ToString());

}

 

public void NonVirt()

{

Console.WriteLine(" This is a non-virtual method of {0}", this.ToString());

}

 

public override string ToString()

{

return " object of class A1";

}

 

public void TestMethods()

{

Console.WriteLine(" Testing class A1");

Virt();

NonVirt();

}

 

}

 

class A2: A1

{

public override string ToString()

{

return " object of class A2";

}

}


Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.017 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал