Читаем Экстремальное программирование: Разработка через тестирование полностью

assertTrue(new Franc(5). equals(new Franc(5)));

assertFalse(new Franc(5). equals(new Franc(6)));

}

Снова дублирование. Целых две строчки! Этот грех нам тоже придется искупить. Но чуть позже.

Теперь, когда тесты на месте, мы можем сделать класс Franc производным от класса Money:

Franc

class Franc extends Money {

private int amount;

}

Далее мы можем уничтожить поле amount в классе Franc, так как это значение будет храниться в одноименном поле класса Money:

Franc

class Franc extends Money {

}

Метод Franc.equals() выглядит фактически так же, как и метод Money.equals(). Сделав их абсолютно одинаковыми, мы сможем удалить реализацию этого метода из класса Franc. При этом смысл нашей программы не изменится. Для начала изменим объявление временной переменной:

Franc

public boolean equals(Object object) {

Money franc = (Franc) object;

return amount == franc.amount;

}

После этого изменим операцию преобразования типа:

Franc

public boolean equals(Object object) {

Money franc = (Money) object;

return amount == franc.amount;

}

Теперь, даже не меняя имя временной переменной, можно видеть, что метод получился фактически таким же, как одноименный метод в классе Money. Однако для пущей уверенности переименуем временную переменную:

Franc

public boolean equals(Object object) {

Money money = (Money) object;

return amount == money.amount;

}

$5 + 1 °CHF = $10, если курс обмена 2:1

$5 * 2 = $10

Сделать переменную amount закрытым (private) членом

Побочные эффекты в классе Dollar?

Округление денежных величин?

equals()

hashCode()

Равенство значению null

Равенство объектов

5 CHF * 2 = 1 °CHF

Дублирование Dollar/Franc

Общие операции equals()

Общие операции times()

Сравнение франков (Franc) и долларов (Dollar)

Теперь нет никакой разницы между методами Franc.equals() и Money.equals(), и мы можем удалить избыточную реализацию этого метода из класса Franc. Запускаем тесты. Они выполняются успешно.

Что должно происходить при сравнении франков и долларов? Мы рассмотрим этот вопрос в главе 7.

В данной главе мы

• поэтапно переместили общий код из одного класса (Dollar) в суперкласс (Money);

• сделали второй класс (Franc) подклассом общего суперкласса (Money);

• унифицировали две реализации метода equals() и удалили избыточную реализацию в классе Franc.

<p>7. Яблоки и апельсины</p>

$5 + 1 °CHF = $10, если курс обмена 2:1

$5 * 2 = $10

Сделать переменную amount закрытым (private) членом

Побочные эффекты в классе Dollar?

Округление денежных величин?

equals()

hashCode()

Равенство значению null

Равенство объектов

5 CHF * 2 = 1 °CHF

Дублирование Dollar/Franc

Общие операции equals()

Общие операции times()

Сравнение франков (Franc) и долларов (Dollar)

В конце главы 6 перед нами встал интересный вопрос: что будет, если мы сравним франки и доллары? Мы немедленно добавили соответствующий пункт в список предстоящих задач. Нам никак не избавиться от этой мысли. И в самом деле, что произойдет?

public void testEquality() {

assertTrue(new Dollar(5). equals(new Dollar(5)));

assertFalse(new Dollar(5). equals(new Dollar(6)));

assertTrue(new Franc(5). equals(new Franc(5)));

assertFalse(new Franc(5). equals(new Franc(6)));

assertFalse(new Franc(5). equals(new Dollar(5)));

}

Тест завершается неудачей. С точки зрения написанного кода доллары – это франки. Прежде чем у наших швейцарских клиентов глаза вылезут на лоб, давайте попробуем исправить код. Код сравнения двух денежных значений должен убедиться в том, что он не сравнивает доллары с франками. Для этого мы должны проверить классы сравниваемых объектов – два объекта класса Money считаются равными только в том случае, если у них равны значения amount и классы.

public boolean equals(Object object) {

Money money = (Money) object;

return amount == money.amount

&& getClass(). equals(money.getClass());

}

Подобное использование классов, по правде сказать, отдает неприятным запашком. Предпочтительнее было бы использовать критерий из области финансов, а не из области объектов языка Java. Однако на текущий момент в нашей программе еще нет ничего, что соответствовало бы финансовому понятию «валюта», и пока я не вижу достаточно весомой причины, чтобы вводить в программу подобное понятие. Поэтому пока оставим код таким, какой он есть.

$5 + 1 °CHF = $10, если курс обмена 2:1

$5 * 2 = $10

Сделать переменную amount закрытым (private) членом

Побочные эффекты в классе Dollar?

Округление денежных величин?

equals()

hashCode()

Равенство значению null

Равенство объектов

5 CHF * 2 = 1 °CHF

Дублирование Dollar/Franc

Общие операции equals()

Общие операции times()

Перейти на страницу:

Все книги серии Библиотека программиста

Программист-фанатик
Программист-фанатик

В этой книге вы не найдете описания конкретных технологий, алгоритмов и языков программирования — ценность ее не в этом. Она представляет собой сборник практических советов и рекомендаций, касающихся ситуаций, с которыми порой сталкивается любой разработчик: отсутствие мотивации, выбор приоритетов, психология программирования, отношения с руководством и коллегами и многие другие. Подобные знания обычно приходят лишь в результате многолетнего опыта реальной работы. По большому счету перед вами — ярко и увлекательно написанное руководство, которое поможет быстро сделать карьеру в индустрии разработки ПО любому, кто поставил себе такую цель. Конечно, опытные программисты могут найти некоторые идеи автора достаточно очевидными, но и для таких найдутся темы, которые позволят пересмотреть устоявшиеся взгляды и выйти на новый уровень мастерства. Для тех же, кто только в самом начале своего пути как разработчика, чтение данной книги, несомненно, откроет широчайшие перспективы. Издательство выражает благодарность Шувалову А. В. и Курышеву А. И. за помощь в работе над книгой.

Чед Фаулер

Программирование, программы, базы данных / Программирование / Книги по IT

Похожие книги