Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка - Основи Програмування C_.doc
Скачиваний:
46
Добавлен:
18.12.2018
Размер:
1.44 Mб
Скачать

5. Поняття про поліморфізм.

Поліморфізм – наступний з трьох принципів ООП. Його застосування дозволяє створювати у похідних класах методи, які мають той самий інтерфейс, що й методи базового класу, проте відмінну функціональність.

Припустимо, що ми маємо клас BankAccount, що описує функціонування банківського рахунку. Крім звичайного банківського рахунку можна створити і інші – наприклад, депозитний рахунок DepositAccount, як похідний клас від BankAccount.

using System;

namespace BankAccount

{

class BankAccount // Це банківський рахунок

{

protected double money; // розмір вкладу

private long numAccount; // номер рахунку

// властивість - повертає розмір вкладу

public double Money

{

get { return money; }

}

// конструктор

public BankAccount(long numAccount_, double money_)

{

money = money_;

numAccount = numAccount_;

}

// поповнення рахунку

public void setMoney(long numAccount_, double sum)

{

if (numAccount_ != numAccount)

Console.WriteLine("Неправильний номер рахунку");

else money += sum;

}

// одержання грошей

public void getMoney(long numAccount_, double sum)

{

if (numAccount_ != numAccount)

Console.WriteLine("Неправильний номер рахунку");

else

if (money >= sum)

money -= sum;

else Console.WriteLine("Ви перевищили свій баланс");

}

// нарахування відсотків - бонус 6 %

public void setBonus()

{ money += money * 0.06; }

}

// Це депозитний банківський рахунок

class DepositAccount : BankAccount

{

private int termin; // термін депозиту

public DepositAccount(long numAccount_, double money_,

int termin_) : base (numAccount_, money_)

{ termin = termin_; }

}

class Program

{

static void Main()

{

// відкрили рахунок

BankAccount myBankAccount = new BankAccount(1, 1000);

Console.WriteLine("На рахунку - {0} грн.",

myBankAccount.Money);

myBankAccount.getMoney(1, 200); // зняли гроші

Console.WriteLine("На рахунку - {0} грн.",

myBankAccount.Money);

myBankAccount.setMoney(1, 200); // поповнили рахунок

Console.WriteLine("На рахунку - {0} грн.",

myBankAccount.Money);

myBankAccount.setBonus(); // одержали бонус

Console.WriteLine("На рахунку - {0} грн.",

myBankAccount.Money);

DepositAccount myDepositAccount =

new DepositAccount(1, 5000, 3);

Console.WriteLine("На депозитному рахунку - {0} грн.",

myDepositAccount.Money);

myDepositAccount.setBonus();

Console.WriteLine("На депозитному рахунку - {0} грн.",

myDepositAccount.Money);

}

}

}

В результаті роботи цієї програми на екрані одержимо такі повідомлення:

На рахунку – 1000 грн.

На рахунку – 800 грн.

На рахунку – 1000 грн.

На рахунку – 1060 грн.

На депозитному рахунку - 5000 грн.

На депозитному рахунку - 5300 грн.

Очевидно, що невірно нараховувати бонус однаковим чином по різних видах внесків на банківські рахунки. Отже, у кожному похідному класі необхідно мати для цього окремий метод. Зручно мати дійсно різні функції проте з ідентичним інтерфейсом. Досягти цього можна двома шляхами. Один з них можливий завдяки підтримці поліморфізму у мові С#. Ідея полягає у тому, що деякий метод базового класу може заміщатись у похідних класах. Таким чином, однакове звертання до екземплярів різних похідних класів призводить до різних відгуків – адже викликаються різні методи хоча й з однаковою сигнатурою. Це доволі складний механізм, і щоб підключити його підтримку, метод (або властивість) базового класу, який буде заміщатись у похідному класі, позначають службовим словом virtual. Відповідний метод у похідному класі позначають override:

class Base

{

public virtual void DoSomething() { }

public virtual int SomeProperty

{ get { return 0; } }

}

class SubBase : Base

{

public override void DoSomething () { }

public override int SomeProperty

{ get { return 0; } }

}

Інший шлях – визначити у похідному класі метод із модифікатором new, який буде перекривати (приховувати) відповідний метод базового класу. Тоді для екземплярів базового та похідних класів викликатимуться відповідно різні методи.

class Base

{

public void DoSomething () { }

public int SomeProperty

{ get { return 0; } }

}

class SubBase : Base

{

public new void DoSomething () { }

public new int SomeProperty

{ get { return 0; } }

}

Коли при визначенні члену класу використовується модифікатор new, цей новий член класу викликається замість відповідного члену базового класу, який виявляється перекритим. Тим не менше і перекритий член класу може бути викликаний, якщо екземпляр похідного класу приводиться до типу базового класу:

SubBase sb = new SubBase ();

sb.DoSomething (); // викликається новий метод

Base b = (Base)sb;

b.DoSomething (); // викликається старий метод

Зробимо поліморфним метод setBonus(). Для цього у базовому класі BankAccount змінимо його визначення наступним чином (з’являється службове слово virtual):

public virtual void setBonus() // бонус 6 %

{ money += money * 0.06; }

У похідному класі DepositAccount визначимо свій метод setBonus() із службовим словом override:

// бонус залежить від терміну

public override void setBonus()

{ money += money * 0.15 * termin / 4; }

Тепер звертання myDepositAccount.setBonus() означає виклик методу setBonus() похідного класу DepositAccount, а звертання myBankAccount.setBonus() – виклик однойменного методу базового класу BankAccount. Проте це ще далеко не всі можливості віртуальних функцій.