Розширення класів Android

&nbsp

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

Деякі класи в бібліотеках Android розроблялися спеціально для створення дочірніх класів (наприклад, клас BaseAdapter з androidwidgets і AsyncTask, який ми опишемо трохи нижче) Але взагалі створення підкласів – не та задача, до якої можна ставитися легковажно

Підклас може повністю замінити поведінку будь нефінального методу у своєму суперкласі і тим самим абсолютно порушити архітектурний контракт класу В системі типів Java ніщо не заважає, наприклад, підкласу TextBox перевизначити метод addTextChangedListener так, що він буде ігнорувати власний аргумент і не буде повідомляти клієнтів зворотного виклику про зміни, що відбуваються у вмісті текстового поля (В даному випадку можна уявити собі, наприклад, реалізацію «безпечного» текстового поля, вміст якого приховано)

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

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

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

Можна мінімізувати ймовірність виникнення подібної проблеми, викликаючи сверхреалізацію (superimplementation) для перевизначеного методу таким чином:

Таким чином, ви гарантуєте, що ваша реалізація доповнює, але не замінює собою існуюче поведінка, навіть якщо з часом реалізація суперкласу зміниться Існує правило написання коду, просуває в деяких співтовариствах розробників, яке формулюється як: «Розробляй в розрахунку на розширення» Правило постулює, що всі методи повинні бути або абстрактними, або фінальними Це правило може здатися драконівським, але подумайте самі: адже переобумовленої метод обовязково порушить семантичний контракт обєкту і, щоб не допустити цього, потрібно як мінімум викликати сверхреалізацію

Джерело: Android Програмування на Java для нового покоління мобільних пристроїв

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


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

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

Ваш отзыв

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

*

*