Part 1-5
フラン(CHF)も扱えるようにする
TODOList.md
レートが2:1の場合、$5+10CHF=$10
Moneyの丸め処理
hashCode()
nullとの等価性
オブジェクトとの等価性
5CHF * 2 = 10CHF
- 新しいテスト
FrancTest.java
public class FrancTest {
@Test
public void testFrancMultiplication(){
Franc five = new Franc(5);
assertEquals(new Franc(10),five.times(2));
assertEquals(new Franc(15),five.times(3));
}
}
- リファクタリングする前提でコピペ実装
Franc.java
class Franc {
private int amount;
Franc(int amount){
this.amount = amount;
}
Franc times(int multiplier){
return new Franc(amount * multiplier);
}
public boolean equals(Object object){
Franc franc = (Franc)object;
return amount == franc.amount;
}
}
- コピペした罪悪感を持ちつつ、コピペによってあらたに発生したタスクTODOListに加えておく
TODOList.md
レートが2:1の場合、$5+10CHF=$10
Moneyの丸め処理
hashCode()
nullとの等価性
オブジェクトとの等価性
DollarとFrancの重複
equalsの一般化
timesの一般化
コピペはよくある話なのでこれをどう改善していくか
この章で行ったこと
バリエーションに対してコピペした
コピペはリファクタリングする前提でTODOList書いた
Part 1-6
共通化に向けて
- DollarとFrancに共通なスーパークラスを作成していく
Money.java
class Money {
}
Dollar.java
class Dollar extends Money {
private int amount;
}
- 次にインスタンス変数を移動する
Money.java
class Money {
protected int amount;
}
Dollar.java
class Dollar extends Money {
}
ここまで、テストは失敗しないことを確認する
equalsの修正にとりかかる
Dollar.java
public boolean equals(Object object){
Money dollar = (Money)object;
return amount == dollar.amount;
}
- equalsをMoneyに移植できるようになる
Money.java
class Money {
protected int amount;
public boolean equals(Object object){
Money money = (Money)object;
return amount == money.amount;
}
}
- Francのequalsを削除したいが、等価性のテストを行っていない
- ここでFrancのequalsに対するテストを追加しておく
DollarFrancTest.java
@Test
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)));
}
- FrancにもDollarと同じ修正を行い、equals実装をMoneyにまとめる
この章で行ったこと
共通コードをスーパークラスへ移動
冗長な実装を削除する前にequals実装を一致させた
Part 1-7
共通化の結果...
- DollarとFrancが同様に扱われてしまう...
DollarFrancTest.java
@Test
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.java
public boolean equals(Object object){
Money money = (Money)object;
return amount == money.amount && getClass().equals(money.getClass());
}
この章で行ったこと
おかしな状態をテストに変換した
テストを動作させるようにした
DollarTest.java
public class DollarTest {
@Test
public void testMultiplication(){
Dollar five = new Dollar(5);
assertEquals(new Dollar(10),five.times(2));
assertEquals(new Dollar(15),five.times(3));
}
@Test
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)));
}
}
FrancTest.java
public class FrancTest {
@Test
public void testFrancMultiplication(){
Franc five = new Franc(5);
assertEquals(new Franc(10),five.times(2));
assertEquals(new Franc(15),five.times(3));
}
}
Money.java
class Money {
protected int amount;
public boolean equals(Object object){
Money money = (Money)object;
return amount == money.amount && getClass().equals(money.getClass());
}
}
Dollar.java
class Dollar extends Money {
Dollar(int amount){
this.amount = amount;
}
Dollar times(int multiplier){
return new Dollar(amount * multiplier);
}
}
Franc.java
class Franc extends Money{
Franc(int amount){
this.amount = amount;
}
Franc times(int multiplier){
return new Franc(amount * multiplier);
}
}