русс | укр

Мови програмуванняВідео уроки php mysqlПаскальСіАсемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование


Linux Unix Алгоритмічні мови Архітектура мікроконтролерів Введення в розробку розподілених інформаційних систем Дискретна математика Інформаційне обслуговування користувачів Інформація та моделювання в управлінні виробництвом Комп'ютерна графіка Лекції


Реалізація інтерфейсу


Дата додавання: 2015-01-08; переглядів: 1015.


 

У списку предків класу спочатку вказується його базовий клас, якщо він є, а потім через кому - інтерфейси, які реалізує цей клас. Таким чином, в С# підтримується одиночне спадкоємство для класів і множинне - для інтерфейсів. Це дозволяє додати похідному класу властивості декількох базових інтерфейсів, реалізовуючи їх на свій розсуд.

Наприклад, реалізація інтерфейсу IAction в класі Monster показана на лістингу 9.1:

 

Лістинг 9.1. Реалізація інтерфейсу

using System;

 

namespace Iterface

{

interface IAction

{

void Draw();

int Attack(int a);

void Die();

void Passport();

int Power { get; set;}

}

class Monster : IAction

{

public Monster (int health, int ammo, string name)

{

this.health = health;

this.ammo = ammo;

this.name = name;

}

public void Draw()

{

Console.WriteLine( "Тут був " + name );

}

public int Attack(int ammo_)

{

ammo -= ammo_;

if (ammo > 0) Console.WriteLine("Ба-бах!");

else ammo = 0;

return ammo;

}

public void Die()

{

Console.WriteLine("Monster " + name + " RIP");

health = 0;

}

public int Power

{

get

{

return ammo * health;

}

set

{

if (value > 0)

ammo = health = value;

}

}

public void Passport()

{

Console.WriteLine("Monster {0} \t health = {1} ammo = {2}",

name, health, ammo);

}

string name;

int health, ammo;

}

class Class1

{

public static void Act(IAction A)

{

A.Passport();

}

static void Main()

{

Monster X = new Monster( 80, 80, "Вася" ); // 1 Об'єкт класу

X.Draw();

IAction Y = new Monster( 80, 80, "Миша" ); // 2 Об'єкт типу інтерфейсу

Y.Draw();

Console.WriteLine("Power - " + Y.Power);

Y.Power = 100;

Y.Attack(-500);

Y.Draw();

Y.Passport();

Act(Y);

}

}

}

 

Природно, що сигнатури методів в інтерфейсі і реалізації повинні повністю збігатися. Для елементів інтерфейсу, що реалізовуються, в класі слід указувати специфікатор public. До цих елементів можна звертатися двома способами: через об'єкт класу і через об'єкт типу відповідного інтерфейсу. Це показано відповідно в операторах 1 і 2.

 

Результат роботи програми:

Тут був Вася

Тут був Міша

Power - 6400

Ба – бах!

Тут був Міша

Monster Міша health = 100 ammo = 600

Monster Міша health = 100 ammo = 600

 

Існує другий спосіб реалізації інтерфейсу в класі: явна вказівка імені інтерфейсу перед елементом, що реалізовується. Специфікатори доступу при цьому не указуються. До таких елементів можна звертатися в програмі тільки через об'єкт типу інтерфейсу, наприклад:

 

class Monster : IAction

{

int IAction.Power

{

get

{

return ammo * health;

}

}

 

void IAction.Draw()

{

Console.WriteLine( " Тут був " + name );

}

}

IAction Actor = new Monster(10,10,"Maшa");

Actor.Draw(); // звернення через об'єкт типу інтерфейсу

// Monster Vasia = new Monster(50, 50, "Вася" );

// Vasia.Draw(); помилка!

 

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

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

 

interface ITest

{

void Draw();

}

 

interface IAction

{

void Draw();

int Attack( int a );

void Die();

int Power { get; }

}

 

class Monster : IAction, ITest

{

void ITest.Draw()

{

Console.Writel_ine("Testing " + name );

}

void IAction.Draw()

{

Console.WriteLine( " Тут був " + name );

}

}

 

Обидва інтерфейси містять метод Draw з однією і тією ж сигнатурою. Розрізняти їх допомагає явна вказівка імені інтерфейсу. Звертатися до цих методів можна, використовуючи операцію приведення типу, наприклад:

Monster Vasia = new MONSTER( 50, 50, "Вася" );

((Itest)Vasia).Draw(); // результат: Тут був Вася

((Iaction)Vasia).Draw(); // результат: Testing Вася

Втім, якщо від таких методів не потрібна різна поведінка, можна реалізувати метод першим способом (із специфікатором public), компілятор не заперечує

:

class Monster: IAction. ITest

{

public void Draw()

{

Console.WriteLine( " Тут був " + name ):

}

}

До методу Draw, описаного таким чином, можна звертатися будь-яким способом: через об'єкт класу Monster, через інтерфейс IAction або ITest.

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

 


<== попередня лекція | наступна лекція ==>
Синтаксис інтерфейсу | Інтерфейси і спадкоємство


Онлайн система числення Калькулятор онлайн звичайний Науковий калькулятор онлайн