Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Три механизма, обеспечивающие полиморфизм
Под полиморфизмом в ООП понимают способность одного и того же программного текста x1.M(arg1, arg2, … argN);выполняться по-разному, в зависимости от того, с каким объектом связана сущность x. Полиморфизм гарантирует, что вызываемый метод M будет принадлежать классу объекта, связанному с сущностью x. В основе полиморфизма, характерного для семейства классов, лежат три механизма.
В совокупности это и называется полиморфизмом семейства классов. Целевую сущность часто называют полиморфной сущностью, вызываемый метод - полиморфным методом, сам вызов - полиморфным вызовом. 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"; } }
|