Розширення інтерфейсів

Інтерфейси також можуть розширюватися за допомогою ключового слова extended На відміну від класів, допускається розширення інтерфейсом відразу декількох інших інтерфейсів:

interface Shimmer extends FloorWax, DessertTopping {

double amazingPrice()

}

Тип Shimmer розширює FloorWax і DessertTopping це означає, що всі методи і константи, визначені в FloorWax і DessertTopping, є складовою частиною його контракту, і до них ще додається метод amazingPrice

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

interface W { }

interface X extends W { }

class Y implements W { }

class Z extends Y implements X { }

Ситуація частково нагадує знайоме нам ромбовидное спадкування, але на цей раз немає ніяких сумнівів з приводу того, які поля, X або Y, повинні використовуватися у X немає ніяких полів, оскільки це інтерфейс, так що залишається тільки Y Діаграма успадкування буде виглядати наступним чином:

W, X і Y могли б бути інтерфейсами, а Z – класом От як би це виглядало:

interface W { }

interface X extends W { } interface Y extends W { } class Z implements X, Y { }

Z виявляється єдиним класом, що входять у дану ієрархію

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

protected void twiddle(W wRef) { Object obj = wRef

// ..

}

431 Конфлікти імен

Два останніх приклади наочно демонструють, що клас або інтерфейс може бути підтипом більш ніж одного інтерфейсу Виникає питання: що станеться, якщо в батьківських інтерфейсах присутні методи з однаковими іменами Якщо інтерфейси X і Y містять однойменні методи з різною кількістю або типом параметрів, то відповідь проста: інтерфейс Z буде містити два перевантажених методу з однаковими іменами, але різними сигнатурами Якщо ж сигнатури в точності збігаються, то відповідь також простий: Z може містити лише один метод з даною сигнатурою Якщо методи відрізняються лише типом значення, що повертається, ви не можете реалізувати обидва інтерфейсу

Якщо два методи відрізняються тільки типом порушуваних винятків, метод вашого класу зобовязаний відповідати обом оголошеннях з однаковими сигнатурами (кількістю і типом параметрів), але може порушувати свої винятки Однак методи в межах класу не повинні відрізнятися тільки складом порушуваних винятків отже, має бути присутня лише одна реалізація, яка задовольняє обом звязкам throws Пояснимо сказане на прикладі:

interface X {

void setup() throws SomeExeption

}

interface Y {

void setup()

}

class Z implements X, Y {

public void setup() {

// ..

}

}

У цьому випадку клас Z може містити єдину реалізацію, яка відповідає Xsetup і Ysetup Метод може порушувати менше винятків, ніж оголошено в його суперкласі, тому при оголошенні Zsetup необовязково вказувати, що в методі збуджується виключення типу Some Exception Xsetup тільки дозволяє використовувати дане виключення Зрозуміло, все це має сенс лише в тому випадку, якщо одна реалізація може задовольнити контрактами обох методів, – якщо два методи подразумевают щось різне, то вам, як видно, не вдасться написати єдину реалізацію для них

Якщо списки винятків розходяться настільки, що вам не вдається оголосити методи так, щоб вони задовольняли сигнатурам обох інтерфейсів, то ви не зможете ні розширити ці інтерфейси, ні побудувати який реалізує їх клас

З константами інтерфейсів справа йде простіше Якщо в двох інтерфейсах маються константи з однаковими іменами, то ви завжди зможете обєднати їх в дереві спадкування, якщо скористаєтеся уточненими (qualified) іменами констант Нехай інтерфейси PokerDeck і TarotDeck включають константи DECK_SIZE з різними значеннями, а інтерфейс або клас MultiDeck може реалізувати обидва цих інтерфейсу Проте всередині Multi Deck і його підтипів ви повинні користуватися уточненими іменами Poker DeckDECK_SIZE і TarotDeckDECK_SIZE, оскільки просте DECK_SIZE було б двозначним

Джерело: Арнольд К, Гослінг Д – Мова програмування Java (1997)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*