Перевизначення методів і приховування полів

У своєму новому класі ColorAttr ми переопределили і перевантажили метод valueOf,

встановлює значення атрибуту:

Перевантаження (overloading) методу розглядалася нами раніше під цим терміном розуміється створення декількох методів з однаковими іменами, але з різними сигнатурами, за якими ці методи відрізняються один від одного

Перевизначення (overriding) методу означає, що реалізація методу, взята з суперкласу, замінюється вашої власної Сигнатури методів при цьому повинні бути ідентичними Зверніть увагу: перевизначення підлягають тільки нестатичні методи

У класі ColorAttr ми переопределили метод AttrvalueOf (Object), створивши новий метод ColorAttrvalueOf (Object) Цей метод спочатку звертається до реалізації суперкласу за допомогою ключового слова super і потім викликає метод decodeColor Посилання super може використовуватися для виклику методів суперкласу, переобумовлених в даному класі Пізніше ми докладно розглянемо посилання super

У переобумовленої методі повинні зберігатися сигнатура і тип значення Звязка throws переобумовленої методу може відрізнятися від звязки throws методу суперкласу, якщо тільки в першою не оголошуються будь типи винятків, що не входять у вихідне визначення методу У звязці throws переобумовленої методу може бути присутнім менше винятків, ніж у методі суперкласу

Переобумовленої метод може взагалі не мати звязки throws в такому випадку

виключення в ньому не перевіряються

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

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

При виклику методу для деякого обєкта його реалізація вибирається залежно від фактичного типу обєкта При доступі до поля використовується оголошений тип посилання Розібратися в цьому допоможе наступний приклад:

class SuperShow {

public String str = “SuperStr”

public void show() { Systemoutprintln(“Supershow: ” + str)

}

}

class ExtendShow extends SuperShow {

public String str = “ExtendStr”

public void show() {

Systemoutprintln(“Extendshow: ” + str)

}

public static void main(String[] args) { ExtendShow ext = new ExtendShow() SuperShow sup = ext

supshow()

extshow()

Systemoutprintln(“supstr = ” + supstr) Systemoutprintln(“extstr = ” + extstr)

}

}

У нас є всього один обєкт, але на нього вказують два посилання – тип однією з них збігається з типом обєкта, а інша оголошена як посилання на суперклас Ось як виглядають результати роботи даного прикладу:

Extendshow: ExtendStr Extendshow: ExtendStr supstr = SuperStr extstr = ExtendStr

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

Що стосується поля str, то вибір класу, якому належить це поле, здійснюється на підставі оголошеного типу посилання, А не фактичного типу обєкта По суті, кожен обєкт класу ExtendShow містить два поля типу String, кожне з яких називається str одне з них успадковується від суперкласу і ховається іншим, власним полем класу Extend Show:

Ми вже переконалися, що перевизначення методів дозволяє збільшити можливості існуючого коду за рахунок використання його з обєктами, розширені властивості яких не були передбачені розробником Але в тому, що стосується приховування полів, – досить нелегко придумати ситуацію, при якій воно було б корисним

Якщо існуючий метод отримує параметр типу SuperShow і звертається до str через посилання на обєкт-параметр, він завжди буде отримувати Super Showstr, навіть якщо методу насправді було передано обєкт типу Extend Show Якби класи були спроектовані так, щоб для доступу до рядка застосовувався спеціальний метод, то в

цьому випадку був би викликаний перевизначення метод, який повертає ExtendShowstr Це

ще одна з причин, по якій визначення класів з закритими даними, доступ до яких здійснюється за допомогою методів, виявляється кращим

Приховування полів дозволено в Java для того, щоб при новій реалізації існуючих суперкласів можна було включити в них нові поля з атрибутами public або protected, не порушуючи при цьому роботи підкласу Якби використання однакових імен в суперкласі і підкласі було заборонено, то включення нового поля в існуючий суперклас потенційно могло б привести до конфліктів з підкласами, в яких це імя вже використовується У такому випадку заборона на додавання нових полів до існуючих суперкласу повязував би руки програмістам, які не могли б доповнити суперкласу новими полями з атрибутами public або protected Формально можна було б заперечити, що класи повинні містити тільки дані private, але Java підтримує обидві можливості

341 Ключове слово super

Ключове слово super може використовуватися у всіх нестатичних методах класу При доступі до полів або виклику методів ключове слово super являє собою посилання на поточний обєкт як екземпляр суперкласу Використання super виявляється єдиним випадком, при якому вибір реалізації методу залежить від типу посилання У виклику виду supermethod завжди використовується реалізація method з суперкласу, а не його перевизначення реалізація, яка знаходиться десь нижче в ієрархії класів

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

class That {

/ ** Повернути імя класу * /

protected String nm() {

return “That”

}

}

class More extends That {

protected String nm() {

return “More”

}

protected void printNM() { That sref = super

Systemoutprintln(“thisnm() = ” + thisnm()) Systemoutprintln(“srefnm() = ” + srefnm()) Systemoutprintln(“supernm() = ” + supernm())

}

}

А ось як виглядає результат роботи printNM:

thisnm() = More srefnm() = More supernm() = That

Ключове слово super може також застосовуватися для доступу до захищених членам суперкласу

Джерело: Арнольд К, Гослінг Д – Мова програмування 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>

*

*