Конструктори в розширених класах

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

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

Виклик конструктора суперкласу демонструється на прикладі першого конструктора ColorAttr Спочатку отримані імя і значення передаються конструктору суперкласу, яка отримує два аргументи Потім конструктор викликає свій власний метод decodeColor для того, щоб поле myColor посилалося на потрібний колірний обєкт

Ви можете тимчасово відкласти виклик конструктора суперкласу і використовувати замість нього один з конструкторів того ж класу – в цьому випадку замість super () використовується this () Другий конструктор ColorAttr надходить саме так Це було зроблено для того, щоб кожному колірному атрибуту завідомо був привласнений якийсь колір якщо він не вказаний, то за замовчуванням присвоюється колір transparent (тобто прозорий)

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

Сигнатури конструкторів класу ColorAttr в точності збігаються з сигнатурами конструкторів суперкласу, але це ні в якому разі не є обовязковим Іноді буває зручно зробити так, щоб частина або всі конструктори розширеного класу передавали потрібні параметри в конструктори суперкласу і обходилися без своїх

параметрів (або число таких параметрів було б мінімальним) Нерідкі випадки, коли сигнатури конструкторів розширеного класу не мають нічого спільного з сигнатурами конструкторів суперкласу

Мова Java може створити безаргументний конструктор за замовчуванням Робота такого конструктора для розширюваного класу починається з виклику безаргументний конструктора суперкласу Однак, якщо в суперкласі відсутня безаргументний конструктор, розширений клас повинен містити хоча б один конструктор Конструктор розширеного класу за замовчуванням еквівалентний наступному:

public class ExtendedClass extends SimpleClass {

public ExtendedClass() {

super()

}

}

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

ExtendedClass оголошений як public, конструктор за замовчуванням також буде public

331 Порядок виклику конструкторів

При створенні обєкта всім його полях присвоюються початкові значення за замовчуванням в залежності від їх типу (нуль для всіх числових типів, \ u0000 для char, false для boolean і null для посилань на обєкти) Потім відбувається виклик конструктора Кожен конструктор виконується за три фази:

1 Виклик конструктора суперкласу

2 Присвоєння значень полях за допомогою ініціалізаторів

3 Виконання тіла конструктора

Наведемо приклад, який дозволить нам простежити за цією процедурою:

class X {

protected int xMask = 0x00ff

protected int fullMask

public X() {

fullMask = xMask

}

public int mask(int orig) {

return (orig &amp fullMask)

}

}

class Y extends X {

protected int yMask = 0xff00

public Y() {

fullMask |= yMask

}

}

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

Крок

Що відбувається

xMask

yMask

fullMask

0

Присвоєння полях значень за замовчуванням

0

0

0

1

Виклик конструктора Y

0

0

0

2

Виклик конструктора X

0

0

0

3

Ініціалізація полів X

0x00ff

0

0

4

Виконання конструктора X

0x00ff

0

0x00ff

5

Ініціалізація полів Y

0x00ff

0xff00

0x00ff

6

Виконання конструктора Y

0x00ff

0xff00

0xffff

Цей порядок має ряд важливих наслідків для виклику методів під час конструювання Звертаючись до методу, ви завжди маєте справу з його реалізацією для конкретного обєкта поля, що використовуються в ньому, можуть бути ще не ініціалізовані Якщо на наведеному вище кроці 4 конструктор X викличе метод mask, то маска буде мати значення 0x00ff, а не 0xffff, незважаючи на те що в більш пізньому виклику mask (після завершення конструювання обєкта) буде використано значення 0xffff

Крім того, уявіть собі ситуацію, в якій клас Y перевизначає реалізацію mask так, щоб в обчисленнях явно використовувалося поле yMask Якщо конструктор X використовує метод mask, насправді буде викликаний mask класу Y, а в цей момент значення yMask дорівнює нулю замість очікуваного 0xff00

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

Вправа 32

Наберіть код наведених вище класів X і Y і включіть в нього оператори виводу для спостереження за значеннями масок Напишіть метод main і запустіть його, щоб ознайомитися з результатами Перевизначите mask в класі Y і знову виконайте тестування

Вправа 33

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

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

*

*