Лістинг 8.7. Використання інтерфейсу



package usinginterfacedemo;ILl

// Интерфейс:

interface Mathematica{

// Поле-константа:

int TEN=10;

// Объявление методов:

int factorial (int n);

double power(double x,int n);

}

// Класс реализует интерфейс:

class MyMath implements Mathematica {

// Описание метода интерфейса (факториал):

public int factorial(int n){

int s=1,i;

for(i=n;i>0;s*=i--);

return s;}

// Описание метода интерфейса (возведение в степень):

public double power(double x,int n){

double s=1;

for(int i=1;i<=n;s*=x,i++);

return s; }

// Метод для отображения результатов вызова методов:

void show(double x,int n){

System.out.println("Первый аргумент: "+x);

System.out.println("Второй аргумент: "+n);

System.out.println("Факториал: "+factorial(n));

System.out.println ("Возведение в степень: *"+power(x,TEN));}

}

// Головной клас програми

public class UsingInterfacedemo {

public static void main(String[] args){

// Создание объекта класса:

MyMath obj=new MyMath();

// Переменные для передачи аргументами.

// Определяются через статическое поле-константу:

int n=Mathematica.TEN/3;

double x=(double)MyMath.TEN/n-n;

// Вызов метода show():

obj.show(x,n);}

}

В інтерфейсі Mathematica оголошена целочисленная константа TEN зі значенням 10 і два методи. Метод factorial() має цілочисельний аргумент і повертає результатом значення цілого типу. Метод power() приймає два аргументи - перший типу double і другий типу int. Повертається методом значення типу double. Це ті формальні позиції, яким повинні відповідати описувані при реалізації інтерфейсу методи.

Інтерфейс Mathematica реалізується в класі MyMath. Зокрема, у класі описуються методи factorial() і power() так, що методом factorial() обчислюється факторіал для цілого числа, переданого аргументом методу, а методом power() перший аргумент зводиться в целочисленную ступінь, передану через другий аргумент.

Зверніть увагу, що методи, успадковані в класі з інтерфейсу, описуються з ключовим словом public. Це обов'язкова умова.

Методом show() в консольне вікно виводиться кілька повідомлень, що містять інформацію про те, які аргументи передаються методу і який результат виклику методів factorial() і power().

У головному методі програми командою MyMath obj = new MyMath () создається об'єкт класу MyMath. Командами int n=Mathematica.TEN/3 і double x=(double)MyMath.TEN/n-n оголошуються і инициализируются на основі значення статичної константи TEN, які потім в команді obj.show(х,n) передаються аргументами методу show().

Статичне постійне поле TEN оголошено в інтерфейсі Mathematica. Звернутися до цього поля можна через ім'я інтерфейсу, тобто в формате Mathematica.TEN. Інтерфейс Mathematica реалізується в класі MyMath. Це як якщо б поле було описано в цьому класі. Тому всередині класу до поля TEN можна звернутися по імені. Поза класу, крім інструкції Mathematica.TEN, до поля можна звернутися через інструкцію MyMath.TEN, тобто як до статичної полю класу.

В результаті виконання програми у консолі з'являються наступні повідомлення:

Перший аргумент: 0.3333333333333335

Другий аргумент: 3

Факторіал: 6

Піднесення до степеня: 1.6935087808430364Е-5

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

interface інтерфейс_1 extends інтерфейс_2 {

/ / програмний код інтерфейсу

}

Наприклад, блок коду з інтерфейсами, успадкуючи один одного, може виглядати так:

interface InterfaceA {

void Fl ();

double F2 (int n);

}

interface InterfaceB extends InterfaceA {

int F3 (double x);

}

В даному випадку оголошується інтерфейс InterfaceA, у якого два методи: F1() і F2(). На його основі шляхом наслідування створюється інтерфейс InterfaceB. Безпосередньо в тілі цього інтерфейсу описаний метод F3(). Разом з тим, в інтерфейсі InterfaceB з інтерфейсу InterfaceA успадковуються методи F1() і F2(). На практиці це означає, що клас реализующій інтерфейс InterfaceB, повинен містити (якщо він тільки не абстрактний) опис усіх трьох методов F1(), F2() і F3().

Як у випадку з класами, інтерфейс може успадковувати тільки один інтерфейс. Зате клас може реалізувати відразу кілька інтерфейсів.

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

class класс_1 extends класс_2 implements інтерфейс_1, інтерфейс_2, ... {

// код класу

}

Після ключового слова class і імені класу слідує ключове слово extends та ім'я суперкласу, потім ключове слово implements і через кому перераховуються реалізовані інтерфейси. Наступний програмний код ілюструє ситуацію, коли в підкласі реалізується кілька інтерфейсів.

class Base{

 String text;

void show() {

System.out.println(text);}

 }

interface InterfaceA{

String getText();

 Void set(String text);}

 interface InterfaceB{ void showText();

}

class SubBase extends Base implements InterfaceA, InterfaceB{

public String getText(){

return text;}

 public void set(String text){

this.text=text;}

 public void showText(){

System.out.println("Текстовое поле:");

show();}

}

У цьому невеликому ілюстративному фрагменті програмного коду оголошується клас Base з текстовим полем text і методом show(), який відображає в консольному вікні значення текстового поля. Також оголошені два інтерфейси. В інтерфейсі InterfaceA оголошуються методи getText() (без аргументів, повертає значення типу String) і set() (приймає текстовий аргумент і не повертає результат).

В інтерфейсі InterfасеВ оголошується метод showText() (без аргументів і не повертає результат). Клас SubBase успадковує клас Base і реалізує інтерфейси InterfaceA і InterfасеВ. Як наслідок в класі SubBase незримо присутній текстове поле text і метод show(), а також описуються методи getText(), set() і showText ().

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

Теоретично може виявитися так, що два або більше інтерфейсів, реалізованих в класі, мають однакові методи. У цьому випадку в класі, реализующем інтерфейси, описується один метод. Це означає, що при "накладанні" методів з різних інтерфейсів не виникає конфлікту, пов'язаного з тим, що один метод описаний двічі. Тут проявляється гібкість інтерфейсів і криється одна з причин, по якій в Java відмовилися від багаторазового успадкування класів (коли один клас створюється на основі відразу декількох класів).

На відміну від Java, в C ++ багаторазове успадкування дозволено. З цим механізмом пов'язаний ряд проблем, причини яких, як показує досвід, криються не безпосередньо в самому принципі наслідування, а конкретної реалізації методів успадкованих класів. З іншого боку, багаторазове успадкування - дуже потужний і ефективний механізм. У Java ця дилема дозволена за допомогою концепції інтерфейсів. Багаторазове успадкування фактично реалізовано через реалізацію кількох інтерфейсів в класі. При цьому, оскільки в інтерфейсах методи не описані, а тільки оголошені, проблема з несумісністю різних описів методів здебільшого вирішена.

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

ІНТЕРФЕЙСНА ЗМІННА

Ще одна важлива властивість, пов'язане з інтерфейсами, полягає в тому, що можна створювати об'єктні змінні з типом інтерфейсу - так звані інтерфейсні змінні.При оголошенні інтерфейсної змінної в якості типу змінної вказується ім'я інтерфейсу. Для інтерфейсу об'єкт створити не можна. Як значення інтерфейсної змінної може присвоюватися посилання на об'єкт класу, який реалізує відповідний інтерфейс. Правда, через таку посилання можна отримати доступ тільки до тих методів, які оголошені в інтерфейсі. Розглянемо приклад, представлений в лістингу 8.8.


Дата добавления: 2018-04-15; просмотров: 285; Мы поможем в написании вашей работы!

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






Мы поможем в написании ваших работ!