ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ ch 5-10
AUSG
TDD
10/05/2020
๋ณธ ๊ธ์ ์ผํธ ๋ฐฑ์ <ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ>์ ์ฝ๊ณ ๊ฐ์ธ์ ์ผ๋ก ์ ๋ฆฌํ ๋ด์ฉ์ ๋๋ค. ๋ด์ฉ์ ์ค๋ฅ๊ฐ ์์ ์ ์ง์ ํด์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค.
5์ฅ ์์งํ ๋งํ์๋ฉด
โฆ 10(ํ์จ์ด 2:1์ผ ๊ฒฝ์ฐ)
โฆ10
โฆamount๋ฅผ private์ผ๋ก ๋ง๋ค๊ธฐ
โฆDollar ๋ถ์์ฉ?
โฆ Money ๋ฐ์ฌ๋ฆผ?
โฆequals()
โฆ hashCode()
โฆ Equal null
โฆ Equal object
โฆ 5CHF * 2 = 10CHF
Dollar ๊ฐ์ฒด๋ฅผ ๋น์ทํ๊ฒ ๋ณธ๋ด Franc ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด๋ณธ๋ค. ์ด์ ์ Dollar ํ ์คํธ์์ ์ฝ๋๋ฅผ ๊ฐ์ ธ์จ๋ค.(์ฌ์ฌ์ฉ์ฑ!)
public void testFrancMultiplication() { Franc five = new Franc(5); assertEquals(new Franc(10), five.times(2)); assertEquals(new Franc(15), five.times(3));}
์ด์ ์ด์ ์ Dollar ํ ์คํธ๊ฐ ๊ฒช์๋ ๊ธธ์ ๊ทธ๋๋ก ๋ฐ๋ผ๊ฐ๋ค(๋ณต๋ถ!)
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; }}
์ปดํ์ผ์ ์ผ๋จ ์ฑ๊ณต!
๊ทธ๋ฌ๋ ์ด์ ์ ๋ง๋ค์๋ Dollar ์ฝ๋์ ์ค๋ณต์ด ๋ง๊ธฐ ๋๋ฌธ์, ๋ค์ ์ฅ์์๋ ์ค๋ณต์ ๊ณ ์ณ์ ์ฌ ์์ฑํ ๊ฒ์ด๋ค.
โฆ 10(ํ์จ์ด 2:1์ผ ๊ฒฝ์ฐ)
โฆ10
โฆamount๋ฅผ private์ผ๋ก ๋ง๋ค๊ธฐ
โฆDollar ๋ถ์์ฉ?
โฆ Money ๋ฐ์ฌ๋ฆผ?
โฆequals()
โฆ hashCode()
โฆ Equal null
โฆ Equal object
โฆ5CHF * 2 = 10CHF
โฆ Dollar/Franc ์ค๋ณต
โฆ ๊ณต์ฉ Equals
โฆ ๊ณต์ฉ times
6์ฅ ๋์์จ '๋ชจ๋๋ฅผ ์ํ ํ๋ฑ'
โฆ 10(ํ์จ์ด 2:1์ผ ๊ฒฝ์ฐ)
โฆ10
โฆamount๋ฅผ private์ผ๋ก ๋ง๋ค๊ธฐ
โฆDollar ๋ถ์์ฉ?
โฆ Money ๋ฐ์ฌ๋ฆผ?
โฆequals()
โฆ hashCode()
โฆ Equal null
โฆ Equal object
โฆ5CHF * 2 = 10CHF
โฆ Dollar/Franc ์ค๋ณต
โฆ ๊ณต์ฉ Equals
โฆ ๊ณต์ฉ times
Franc
์ด๋ผ๋ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ํ
์คํธ์ฝ๋๋ฅผ ์์ฑํ์ง๋ง, ๋ณต๋ถํ๋ ๊ณผ์ ์์ Dollar
๊ฐ์ฒด์ ์ค๋ณต์ด ๋๋ฌด ๋ง์ด ์๊ฒจ๋ฒ๋ ธ๋ค.
๋ฐ๋ผ์ ๋ ๊ฐ์ฒด์ ์ค๋ณต๋๋ ์ฝ๋๋ฅผ ๊ณตํต ์์ ํด๋์ค Money
์ ์ฝ๋๋ก ๋บ ํ, Dollar
์ Franc
์ด ๋ชจ๋ ์ด ํด๋์ค๋ฅผ ์์๋ฐ๊ฒ ํ ๊ฒ์ด๋ค.
class Money{ protected int amount; // ํ์ ํด๋์ค(Dollar, Franc)์์๋ ๋ณ์๋ฅผ ๋ณผ ์ ์๋๋ก ๊ฐ์์ฑ์ private -> protected๋ก ๋ณ๊ฒฝ}class Dollar extends Money {}
amount
๋ฅผ Money
์ ํ๋๋ก ๋บ๋ค๋ฉด, ๋ค์์ equals
์ฝ๋๋ฅผ ๋นผ ์ฌ๋ฆด ์ฐจ๋ก๋ค.
// Moneypublic boolean equals(Object object) { Money money = (Money) object; return amount == money.amount;}
์์ ๊ณผ์ ์ ์ถ์ฝํด์ ํ๋ฒ์ ์ ์์ง๋ง, ์ฑ
์์๋ Dollar
๊ฐ์ฒด ๋ด์์ ํ์
์บ์คํ
ํ๋, ๋ณ์๋ช
ํ๋๋ฅผ ๋ฐ๊ฟ๋๋ง๋ค ํ
์คํธ์ฝ๋์ ์ด์์ด ์๋์ง ๋๋ ค๊ฐ๋ฉฐ ์ํํ๊ณ , Money
์ ๋ฉ์๋๋ก ์์ ํ ๋ฆฌํฉํ ๋งํ๋ค๊ณ ์๊ฐ๋ ๋ Money
๋ก ์ฎ๊ธด๋ค. ์ ๋ง ์ฐจ๊ทผ์ฐจ๊ทผ ์กฐ๊ธ์ฉ ํ๋ ์
.
Money
์ ์ผ๋ฐํ๋ equals
์ ์ฝ๋๊ฐ ์์ผ๋ฏ๋ก, ์ด์ Franc
์ equals
๋ฅผ ์ ๊ฑฐํด์ผํ๋ค.
๊ทธ๋ฐ๋ฐ ์ด์ ์ ๋ง๋ค์ด๋๋ ๋์น์ฑ ํ
์คํธ( testmultiplication
)๊ฐ Franc
๊ฐ์ฒด์ ๋ํด์๋ ๋น๊ตํ๊ณ ์์ง ์์ผ๋ฏ๋ก, Franc
๋ ํ
์คํธ ํ ์ ์๋๋ก ํ
์คํธ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ค. (๋ชจ๋ ํ
์คํธ์ฝ๋๋ ๋ด๋ถ ๋ก์ง์ ํ
์คํธํ๋๊ฒ์ด ์๋๋ผ ์ธ๋ถ๋ก ๋๋ฌ๋๋ ๊ฒฐ๊ณผ-๊ทธ๋์ equals์ธ๊ฑฐ์ผ?-์ ๋ํด์ ํ
์คํธํ๋ค. ์ธ๋ถ, ์ธ๋ถ.)
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))); /* ์ค๋ณต๋ assertTrue, assertFalse ์ฝ๋์ ๋ํด์๋ ์ถํ์ ๋ฆฌํฉํ ๋งํ๋ค. */}
Franc
์ equals
๋ Dollar
์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฆฌํฉํ ๋ง ํ ํ, ์์ ํด๋์ค Money
์ equals
์ ๋ค๋ฅธ ์ ์ด ์์์ ํ์ธํ๊ณ ์ ๊ฑฐํ๋ค.
โฆ 10(ํ์จ์ด 2:1์ผ ๊ฒฝ์ฐ)
โฆ10
โฆamount๋ฅผ private์ผ๋ก ๋ง๋ค๊ธฐ
โฆDollar ๋ถ์์ฉ?
โฆ Money ๋ฐ์ฌ๋ฆผ?
โฆequals()
โฆ hashCode()
โฆ Equal null
โฆ Equal object
โฆ5CHF * 2 = 10CHF
โฆ Dollar/Franc ์ค๋ณต
โฆ๊ณต์ฉ Equals
โฆ ๊ณต์ฉ times
โฆ Franc์ Dollar ๋น๊ตํ๊ธฐ
7์ฅ ์ฌ๊ณผ์ ์ค๋ ์ง
*์๋ก ๋ค๋ฅธ ๊ณผ์ผ์ธ ์ฌ๊ณผ์ ์ค๋ ์ง์ ๊ฐ์ด, ์๋ก ๋ค๋ฅธ ๊ฒ์ ๋น๊ตํ ์ ์์์ ์ด๋ฅด๋ ๊ด์ฉ์ด๊ตฌ์ด๋ค.
โฆ 10(ํ์จ์ด 2:1์ผ ๊ฒฝ์ฐ)
โฆ10
โฆamount๋ฅผ private์ผ๋ก ๋ง๋ค๊ธฐ
โฆDollar ๋ถ์์ฉ?
โฆ Money ๋ฐ์ฌ๋ฆผ?
โฆequals()
โฆ hashCode()
โฆ Equal null
โฆ Equal object
โฆ5CHF * 2 = 10CHF
โฆ Dollar/Franc ์ค๋ณต
โฆ๊ณต์ฉ Equals
โฆ ๊ณต์ฉ times
โฆ Franc์ Dollar ๋น๊ตํ๊ธฐ
๋ง์ฝ์, Franc
๊ณผ Dollar
๋ฅผ ๋น๊ตํ๋ค๋ฉด ์ด๋ค ๊ฒฐ๊ณผ๊ฐ ์ผ์ด๋ ๊น?
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)));}
๋น์ฐํ java ๊ฐ์ฒด์ Franc
์ Dollar
๋ ๋ค๋ฅธ ๊ฐ์ฒด์ด๋ฏ๋ก ์คํจํ๋ค.
์ด๋ฅผ ๋ช ์์ ์ผ๋ก ํ์ฌ, ๋ ํตํ(Currency)๋ฅผ ๋น๊ตํ์ฌ ๋ค๋ฅด๋ฉด ๋์น์ฑ ๋น๊ต๋ฅผ ํต๊ณผํ์ง ๋ชปํ๋๋ก ์ฝ๋๋ฅผ ์์ฑํ์.
public boolean equals(Object object) { Money money = (Money) object; return amount == money.amount && getClass().equals(money.getClass());}
์์ง ํตํ(Currency)์ ๊ฐ๋
์ด ์์ผ๋ฏ๋ก, equals
๋ฉ์๋๋ ๋ ๊ฐ์ฒด(ํตํ)์ ํด๋์ค๊ฐ ์์ ํ ๋์ผํด์ผ ํ๋ค๋ ์กฐ๊ฑด์ ์ถ๊ฐํ๋ค. ๊ทธ๋ฌ๋ ์ด๋ ์๋ฐ ์ฝ๋(ํด๋์ค)์ ์ธ ์ธก๋ฉด์ด์ง, ์ฌ์ ๊ฐ๋
์ ์ผ๋ก ๋ช
ํํ ๋น๊ต๊ฐ ์๋๋ค. ์ผ๋จ ๋น์ฅ์ ํตํ ๊ฐ๋
์ ๋ง๋ค์ด์ผ ํ ํ์์ฑ์ ์์ผ๋ ์ผ๋จ ํ ์ผ ๋ชฉ๋ก์ ์ถ๊ฐํด ๋๋ค.
โฆ 10(ํ์จ์ด 2:1์ผ ๊ฒฝ์ฐ)
โฆ10
โฆamount๋ฅผ private์ผ๋ก ๋ง๋ค๊ธฐ
โฆDollar ๋ถ์์ฉ?
โฆ Money ๋ฐ์ฌ๋ฆผ?
โฆequals()
โฆ hashCode()
โฆ Equal null
โฆ Equal object
โฆ5CHF * 2 = 10CHF
โฆ Dollar/Franc ์ค๋ณต
โฆ๊ณต์ฉ Equals
โฆ ๊ณต์ฉ times
โฆFranc์ Dollar ๋น๊ตํ๊ธฐ
โฆ ํตํ?
์ด์ ๋ค์์ฅ์์๋ ๊ณตํต์ times()
์ฝ๋๋ฅผ ์ฒ๋ฆฌํด๋ณด๊ธฐ๋ก ํ๋ค. ๋ฐ๋ผ์ ํผํฉ๋ ํตํ์ ์ฐ์ฐ์ ๋ค๋ฃฐ๊ฒ์ด๋ค.
8์ฅ ๊ฐ์ฒด ๋ง๋ค๊ธฐ
โฆ 10(ํ์จ์ด 2:1์ผ ๊ฒฝ์ฐ)
โฆ10
โฆamount๋ฅผ private์ผ๋ก ๋ง๋ค๊ธฐ
โฆDollar ๋ถ์์ฉ?
โฆ Money ๋ฐ์ฌ๋ฆผ?
โฆequals()
โฆ hashCode()
โฆ Equal null
โฆ Equal object
โฆ5CHF * 2 = 10CHF
โฆ Dollar/Franc ์ค๋ณต
โฆ๊ณต์ฉ Equals
โฆ ๊ณต์ฉ times
โฆFranc์ Dollar ๋น๊ตํ๊ธฐ
โฆ ํตํ?
// Franc codeFranc times(int multiplier) { return new Franc(amount * multiplier)}// Dollar codeDollar times(int multiplier) { return new Dollar(amount * multiplier)}
ํ์ฌ Franc
๊ณผ Dollar
์ times()
์ฝ๋๋ ๊ฐ๋
์ ์ผ๋ก ์์ ํ ๋์ผํ๋ค.(๋ณต๋ถ์ ํํด..)
// Franc codeMoney times(int multiplier) { return new Franc(amount * multiplier)}// Dollar codeMoney times(int multiplier) { return new Dollar(amount * multiplier)}
์์ชฝ ๋ชจ๋ Money
๊ฐ์ฒด๋ฅผ ๋ฐํํ๋๋ก ๋ง๋ค์๋๋ฐ, ๋ ๊ฐ์ฒด์ times ๋ฉ์๋๋ฅผ ๋ค ์ญ์ ํ๊ณ ์์์์ ๋ฆฌํฉํ ๋งํ๋๊ฒ์ ํจ์จ์ ์ธ TDD๊ฐ ์๋ ๊ฒ ๊ฐ๋ค.(์ผ๊ธ์ผ๊ธ, ์ด๊ธ์ด๊ธ!)
Money
ํด๋์ค์ ํ์ ํด๋์ค์ธ Dollar
, Franc
ํด๋์ค์ ์ง์ ์ ์ธ ์ฐธ์กฐ๋ฅผ ํผํ๊ธฐ ์ํด์, Money
๊ฐ์ฒด ๋ด๋ถ์ ํ์ ํด๋์ค ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋๋ก ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ๋ง๋ค๋ฉด ์ด๋จ๊น?
// Money ์ฝ๋// Money ํฉํ ๋ฆฌ ๋ฉ์๋๋ก, dollar ๊ฐ์ฒด๋ฅผ ๋ฐํstatic Dollar dollar(int amount) { return new Dollar(amount);}
public void testMultiplication() { Money five = Money.dollar(5); // ์๋ ์ฝ๋๋ Dollar five = new Dollar(5); assertEquals(new Dollar(10), five.times(2)); assertEquals(new Dollar(15), five.times(3));}
๊ทธ๋ฌ๋ ์ด๋ ๊ฒ ๋ฐ๊พธ์์ ๊ฒฝ์ฐ์, Money.times()
๊ฐ ์กด์ฌํ์ง ์์ผ๋ฏ๋ก ์๋ฌ๋ฅผ ๋ฑ๋๋ค. ๋ฐ๋ผ์ Money๋ฅผ ์ถ์ ํด๋์ค๋ก ๋ณ๊ฒฝํ์ฌ, Money.times()
๋ฅผ ์ ์ธํด์ค๋ค.
// Money ์ฝ๋abstract class Moneyabstract Money times(int multiplier);// ํฉํ ๋ฆฌ ๋ฉ์๋์ ์ ์ธ์ Money๋ก ๋ฐ๊ฟ์ค๋ค.static Money dollar(int amount) { // ์๋ ์ฝ๋๋ static Dollar dollar(int amount) return new Dollar(amount);}// ๋ง์ฐฌ๊ฐ์ง๋ก Franc๋ ๋์ผํ๊ฒ ์์ฑํ๋ค.static Money franc(int amount) { // ์๋ ์ฝ๋๋ static Franc franc(int amount) return new Franc(amount);}
์ด์ ๊ธฐ์กด ํ ์คํธ ์ฝ๋์์ Dollar, Franc ํ์ ๊ฐ์ฒด ์ง์ ํธ์ถ์ ๋ฆฌํฉํ ๋งํด์ค๋ค.
public void testMultiplication() { Money five = Money.dollar(5); assertEquals(Money.Dollar(10), five.times(2)); assertEquals(Money.Dollar(15), five.times(3));}public void testEquality() { assertTrue(Money.dollar(5).equals(Money.dollar(5))); assertFalse(Money.dollar(5).equals(Money.dollar(6))); assertTrue(Money.franc(5).equals(Money.franc(5))); assertFalse(Money.franc(5).equals(Money.franc(6))); assertFalse(Money.franc(5).equals(Money.dollar(5)));}
์ด์ Money์ ํ์ ํด๋์ค Dollar, Franc์ ์กด์ฌ๋ฅผ ํ ์คํธ์์ ์์ ํ ๋ถ๋ฆฌํ๋ค.๋ฐ๋ผ์ ์์๊ตฌ์กฐ๋ฅผ ๋ง์๋๋ก ๋ณ๊ฒฝํ ์ ์๊ฒ ๋์๋ค(์ด๊ฒ ์ด๋ค ๋ง์ธ์ง ์์ง ์ ํํ ์ดํด๊ฐ ๊ฐ์ง๋ ์๋๋ค). ํ ์คํธ ์ฝ๋์์ ํ์ ํด๋์ค์ ์กด์ฌ๋ฅผ ๋ถ๋ฆฌํ๋ค๋ ๊ฒ์ ์ค์ํ ๊ฐ๋ ์ด๋ค. ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํ์ ํด๋์ค๋ฅผ (์ธ๋ถ) ํ ์คํธ ์ฝ๋์์ ๋ผ์ด๋ด๋ ๊ฒ์ ์ ๊ธฐ์ตํด๋์.
๊ทธ๋ฐ๋ฐ ์ด์ ์ ๋ง๋ค์ด๋์๋ testFrancMultiplication()
์ด ์ปค๋ฒํ๋ ๋ถ๋ถ์ด, Dollar์ ๋ํ ๊ณฑํ๊ธฐ ํ
์คํธ์ฝ๋์ธ testMultiplication()
๊ณผ ๋์ผํ ๋ก์ง์ ์ํํ๋ค๋ ๊ฒ์ ์ ์ ์๋ค. ํ์ ํด๋์ค์ ์กด์ฌ ์์ฒด๋ฅผ ํ
์คํธ ์ฝ๋์์ ๋ผ๋ด๋ ค๊ณ ํ๋๋ฐ, ๋ถํ์ํ๊ฒ ํ์ ํด๋์ค์ ๋ํ ํ
์คํธ ์ฝ๋๊ฐ ๋จ์์๋ ์
์ด๋ค.
public void testFrancMultiplication() { Franc five = new Franc(5); assertEquals(new Franc(10), five.times(2)); assertEquals(new Franc(15), five.times(3));}
์ด ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํ์ฌ ์ญ์ ํ ์ง ์ด์ฉ์ง๋, ํ ์ผ ๋ชฉ๋ก์ ์ผ๋จ ์ถ๊ฐํด๋๋๋ก ํ์. ์์ง ์ฝ๋์ ๋ํ ์์ ํ ํ์ ์ ์์ผ๋๊น..
โฆ 10(ํ์จ์ด 2:1์ผ ๊ฒฝ์ฐ)
โฆ10
โฆamount๋ฅผ private์ผ๋ก ๋ง๋ค๊ธฐ
โฆDollar ๋ถ์์ฉ?
โฆ Money ๋ฐ์ฌ๋ฆผ?
โฆequals()
โฆ hashCode()
โฆ Equal null
โฆ Equal object
โฆ5CHF * 2 = 10CHF
โฆDollar/Franc ์ค๋ณต
โฆ๊ณต์ฉ Equals
โฆ ๊ณต์ฉ times
โฆFranc์ Dollar ๋น๊ตํ๊ธฐ
โฆ ํตํ?
โฆ testFrancMultiplication์ ์ง์์ผํ ๊น?
9์ฅ ์ฐ๋ฆฌ๊ฐ ์ฌ๋ ์๊ฐ(time, ๊ณฑํ๊ธฐ)
โฆ 10(ํ์จ์ด 2:1์ผ ๊ฒฝ์ฐ)
โฆ10
โฆamount๋ฅผ private์ผ๋ก ๋ง๋ค๊ธฐ
โฆDollar ๋ถ์์ฉ?
โฆ Money ๋ฐ์ฌ๋ฆผ?
โฆequals()
โฆ hashCode()
โฆ Equal null
โฆ Equal object
โฆ5CHF * 2 = 10CHF
โฆ Dollar/Franc ์ค๋ณต
โฆ๊ณต์ฉ Equals
โฆ ๊ณต์ฉ times
โฆFranc์ Dollar ๋น๊ตํ๊ธฐ
โฆ ํตํ?
โฆ testFrancMultiplication ์ ๊ฑฐ
ํตํ ๊ฐ๋ ์ ํ ์คํธ์ฝ๋๋ฅผ ์ง๊ธฐ ์ํด์, ํตํ๋ฅผ ํํํ๋ ๊ฐ์ฒด๋ค์ด ํ์ํ๋ค. ๊ฐ๊ฐ ๊ตฌํํ ์๋ ์๊ฒ ์ง๋ง, ์ผ๋จ์ ๋ฌธ์์ด์ ์ฌ์ฉํด์ ํํํ๋ค.
public void testCurrency() { assertEquals("USD", Money.dollar(1).currency()); assertEquals("CHF", Money.franc(1).currency());}
Franc์ Dollar ๋ ํด๋์ค์ ๊ฐ์ currency()
ํจ์๋ฅผ ๊ตฌํํ๊ธฐ ์ํด์, ์ธ์คํด์ค ๋ณ์์ ๋ฌธ์์ด์ ์ ์ฅํ ํ ๋ฉ์๋์์ ๊ทธ๊ฒ์ ๋ฐํํ๊ฒ ๋ง๋ ๋ค.
// Money ์ฝ๋abstract String currency();// Franc ์ฝ๋private String currency;Franc(int amount) { this.amount = amount; currency = "CHF";}String currency() { return currency;}// Dollar ์ฝ๋private String currency;Dollar(int amount) { this.amount = amount; currency = "USD";}String currency() { return currency;}
๋ ํ์ํด๋์ค์ currency()
๊ฐ ๋์ผํ๊ณ , ์ธ์คํด์ค ๋ณ์๋ฅผ ์ ์ธํ๋ ๊ฒ๋ ๋์ผํ๋ฏ๋ก ์ด ๋ ๋ถ๋ถ์ ์์ ํด๋์ค๋ก ์ฌ๋ฆด(push up) ์ ์๊ฒ ๋์๋ค.
// Money ์ฝ๋protected String currency;String currency() { return currency;}
'USD'์ 'CHF' ๋ฌธ์์ด์ ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ก ์ฎ๊ธด๋ค๋ฉด ๋ ์์ฑ์๋ ๋์ผํด์ง๊ฑฐ๊ณ , ๊ณตํต ๊ตฌํ์ ๋ง๋ค ์ ์์ ๊ฒ์ด๋ค.
// Franc ์ฝ๋// Franc์ ์์ฑ์Franc(int amount, String currency) { this.amount = amount; this.currency = "CHF";}
์์ฑ์๋ฅผ ์ธ์์ ์ถ๊ฐํ์๋ค.
์์ฑ์์ ์ธ์๋ฅผ ์ถ๊ฐํ์ผ๋, ๋น์ฐํ ์์ฑ์๋ฅผ ํธ์ถํ๋ ๋ถ๋ถ๋ค์ด ๊นจ์ง๋ค. ๊นจ์ง๋ ๋ถ๋ถ์ ๋ค์๊ณผ ๊ฐ๋ค.
// Money ์ฝ๋// #1static Money franc(int amount) { return new Franc(amount, null);}// Franc ์ฝ๋// #2Money times(int multiplier) { return new Franc(amount * multiplier, null);}
#2์์ times()
๊ฐ ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ํธ์ถํด์ผํ๋๋ฐ, ์์ฑ์๋ฅผ ํธ์ถํ๊ณ ์๋ค. ๋ฐ๋ผ์ ์์ฑ์๋ฅผ ํฉํ ๋ฆฌ ๋ฉ์๋๋ก ์ ๋ฆฌํด์ค๋ค.
// Franc ์ฝ๋// #2Money times(int multiplier) { return Money.franc(amount * multiplier);}
์ด์ #1์์ Money์ ํฉํ ๋ฆฌ๋ฉ์๋ franc()
์ด "CHF"๋ฅผ ์ ๋ฌํ๋๋ก, null๊ฐ์ ๋ฐ๊พธ์ด์ฃผ๋ฉด๋๋ค.
// Money ์ฝ๋// #1static Money franc(int amount) { return new Franc(amount, "CHF");}
๊ทธ๋ฌ๊ณ ๋๋ฉด ๋น๋ก์ ์์ฑ์ Franc์ด "CHF"๋ฅผ ์ธ์๋ก ์๋์ผ๋ก ์ ๋ฌ๋ฐ๋๋ก ๋์์ผ๋ฏ๋ก, ์ธ์คํด์ค ๋ด๋ถ์์ "CHF"๋ฅผ ์์ฑํ์ฌ ๋๊ฒจ์ฃผ์ง ์์๋ ๋๋ค. ์ธ์๋ก ๋ค์ด์จ currency๋ฅผ ๊ทธ๋๋ก ๋๊ฒจ์ฃผ๋ฉด ๋๋ ๊ฒ์ด๋ค.
// Franc ์ฝ๋// Franc์ ์์ฑ์Franc(int amount, String currency) { this.amount = amount; this.currency = currency;}
์ด์ฒ๋ผ ์๊ฒ [constant, ๋ฌธ์์ด ๋ฑ์ ๋๊ฒผ๋ค๊ฐ] - [๊ณตํต ๋ถ๋ถ์ push upํ๊ณ ] - [๋ด๋ถ์ ํ๋์ฝ๋ฉ๋ ์ฝ๋๋ค์ ๋ฆฌํฉํ ๋งํด๊ฐ๋ ๊ฒ]์ด ๊ฑฐ๋ถ๊ฐ์ด ๋ค๊ธด ํ๋ค. ์ ์ฒด์ ์ผ๋ก ๋ณด๋ฉด ๋๋ ์ด๋ฐ ๊ณผ์ ๊ณผ ๋น์ทํ๊ฒ ์ฝ๋๋ฅผ ์งคํ ์ง๋ง, ์ด๊ฑธ ์์์ ์ผ๋ก ํญ์ ๋ฐ๋ผํ๊ธฐ์๋ ๋ฌด๋ฆฌ๊ฐ ์๋๊ฒ๊ฐ๋ค. ์ ์๋ '์ด๋ฐ์์ผ๋ก ํ๋ผ'๋ ๊ฒ์ด ์๋๋ผ '์ด๋ฐ์์ผ๋ก ํ ์ค๋ ์์์ผํ๋ค'๋ผ๋ ์ ์ฅ์ด๋ค.
Dollar๋ ๋์ผํ ๋ฐฉ์์ผ๋ก ๋ณํํ๋ค.
// Money ์ฝ๋// ํฉํ ๋ฆฌ๋ฉ์๋ dollarstatic Money dollar(int amount) { return new Dollar(amount, "USD"); // ํฉํ ๋ฆฌ๋ฉ์๋ dollar๋ ์์ฑ์์ currency์ ํญ์ "USD"๋ฅผ ๋๊ฒจ์ค(ํตํ๋ฅผ ๋ฐ๊พธ๊ณ ์ถ๋ค๋ฉด ์ฌ๊ธฐ๋ง ๊ณ ์น๋ฉด ๋ผ!)}// Dollar ์ฝ๋Dollar(int amount, String currency) { this.amount = amount; this.currency = currency; // ์ธ์๋ฅผ ์ด์ฉํ์ฌ currency ์ธ์คํด์ค๋ณ์๋ฅผ ์ ์ธ}Money times(int multiplier) { return Money.dollar(amount * multiplier); // ์์ฑ์๋ฅผ ํฉํ ๋ฆฌ๋ฉ์๋๋ก ๋์ฒด}
๋ ํ์ ํด๋์ค์ ๊ตฌํ์ด ๋น์ทํด์ก์ผ๋ฏ๋ก , ๊ตฌํ์ ์์ ํด๋์ค๋ก ์ฌ๋ฆฐ๋ค.
// Money ์ฝ๋Money(int amount, String currency) { this.amount = amount; this.currency = currency;}// Franc ์ฝ๋Franc(int amount, String currency) { super(amount, currency);}// Dollar ์ฝ๋Dollar(int amount, String currency) { super(amount, currency);}
โฆ 10(ํ์จ์ด 2:1์ผ ๊ฒฝ์ฐ)
โฆ10
โฆamount๋ฅผ private์ผ๋ก ๋ง๋ค๊ธฐ
โฆDollar ๋ถ์์ฉ?
โฆ Money ๋ฐ์ฌ๋ฆผ?
โฆequals()
โฆ hashCode()
โฆ Equal null
โฆ Equal object
โฆ5CHF * 2 = 10CHF
โฆ Dollar/Franc ์ค๋ณต
โฆ๊ณต์ฉ Equals
โฆ ๊ณต์ฉ times
โฆFranc์ Dollar ๋น๊ตํ๊ธฐ
โฆํตํ?
โฆ testFrancMultiplication ์ ๊ฑฐ
์ง๊ธ๊น์ง Dollar์ Franc์ ์ค๋ณต ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ฃผ๋ ค๋ค๊ฐ, ์์ ๋ฌธ์ ๋ค(๊ฐ ๋ฉ์๋, ๋ณ์๋ค์ push up)์ ๋ง์ด ๋ง๋ฅ๋จ๋ ธ๋ค. ํ์ํด๋์ค ์์ฑ์๋ค์ ๋ค๋ฅธ ๋ถ๋ถ๋ค์ ์ผ์น์ํค๊ณ ์ด๋ฅผ push upํ๋ค. ๋, times()
๊ฐ ์์ฑ์๊ฐ ์๋ ํฉํ ๋ฆฌ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋๋ก ๋ง๋ค์๋ค(์์ํด๋์ค๋ก times()
๋ฅผ ์ฎ๊ธฐ๊ธฐ ์ํ ๋ฐํ์ด๋ค) ์ด์ times()
๋ฅผ ์์ํด๋์ค๋ก ์ฌ๋ฆฌ๋ฉด ํ์ ํด๋์ค๋ฅผ ์ ๊ฑฐ ํ ์ค๋น๊ฐ ๊ฑฐ์ ๋ค ๋ ๊ฒ ๊ฐ๋ค.
10์ฅ ํฅ๋ฏธ๋ก์ด ์๊ฐ
โฆ 10(ํ์จ์ด 2:1์ผ ๊ฒฝ์ฐ)
โฆ10
โฆamount๋ฅผ private์ผ๋ก ๋ง๋ค๊ธฐ
โฆDollar ๋ถ์์ฉ?
โฆ Money ๋ฐ์ฌ๋ฆผ?
โฆequals()
โฆ hashCode()
โฆ Equal null
โฆ Equal object
โฆ5CHF * 2 = 10CHF
โฆ Dollar/Franc ์ค๋ณต
โฆ๊ณต์ฉ Equals
โฆ ๊ณต์ฉ times
โฆFranc์ Dollar ๋น๊ตํ๊ธฐ
โฆํตํ?
โฆ testFrancMultiplication ์ ๊ฑฐ
์ด๋ฒ ์ฅ์์ Money๋ฅผ ๋ํ๋ด๋ ํ์ ํด๋์ค๋ฅผ ๋ชจ๋ ์ ๊ฑฐํ๊ณ , Money ํด๋์ค๋ง ๋จ๊ฒจ๋ ๊ฒ์ด๋ค(๋ฆฌํฉํ ๋ง ์์ฑ!)
์ผ๋จ ๋ ํ์ํด๋์ค์ times()
ํจ์๋ฅผ ๋น๊ตํด๋ณด์.
// Franc ์ฝ๋Money times(int multiplier) { return Money.franc(amount * multiplier);}// Dollar ์ฝ๋Money times(int multiplier) { return Money.dollar(amount * multiplier);}
์ดํด๋ณด์๋ ๋ ํจ์๋ฅผ ๋์ผํ๊ฒ ๋ง๋ค ๋ฐฉ๋ฒ์ด ๋ช ํํ์ง ์๋ค. ์ด๋ด ๋๋ ๋ค์ ๋ค๋ก ๋์๊ฐ๋ณธ๋ค. ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ์ธ๋ผ์ธ์์ผ๋ณธ๋ค(๋ฌธ๋งฅ์ ์์ฑ์ ์ฝ๋๋ก ์ฌ์์ฑํ๋ค๋ ์ด์ผ๊ธฐ์ธ ๋ฏ ํ๋ค).
// Franc ์ฝ๋Money times(int multiplier) { return new Franc(amount * multiplier, "CHF");}// Dollar ์ฝ๋Money times(int multiplier) { return new Dollar(amount * multiplier, "USD");}
์ด๋ ๊ฒ ๋ฐ๊พธ๊ณ ๋ณด๋, Franc๊ณผ Dollar๋ ๋ชจ๋ ๊ฐ์ ์ด๋ฆ์ ์ธ์คํด์ค ๋ณ์ currency๋ฅผ ๊ฐ์ง๊ณ ์๋๋ฐ, ๋ง์นจ "CHF", "USD"์ ๋ง์๋จ์ด์ง๋ค. ํ๋์ฝ๋ฉ๋ "CHF", "USD"๋ฅผ ๋์ผํ currency๋ก ๋ฐ๊ฟ๋ณธ๋ค.
// Franc ์ฝ๋Money times(int multiplier) { return new Franc(amount * multiplier, currency);}// Dollar ์ฝ๋Money times(int multiplier) { return new Dollar(amount * multiplier, currency);}
๊ทธ๋ผ ์ด์ ์ฝ๋์์ ๋ค๋ฅธ ๋ถ๋ถ์ ์์ฑ์ ๋ถ๋ถ (new Franc
์ new Dollar
)๋ฐ์ ์๊ฒ ๋์๋ค. ์ด๊ฑธ ๋๋ค Money๋ก ๋ฐ๊ฟ๋ ์ ์๋ํ ๊น..?
์ฌ์ฌ์๊ณ ์์ ์ถ๋ฆฌํ ์๋ ์์ง๋ง, ์ฐ๋ฆฌ๋ ํ ์คํธ์ฝ๋๋ฅผ ๋ฏธ๋ฆฌ ์ง๋จ์ผ๋ ํ๋ฒ ๋๋ ค๋ณด๋ ๊ฒ๋ง์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์๋ค!
// Franc ์ฝ๋Money times(int multiplier) { return new Money(amount * multiplier, currency);}
Money๊ฐ ์ง๊ธ abstract class(์ถ์ ํด๋์ค)์ธ๋ฐ, concrete class(๊ตฌ์ ํด๋์ค)๋ก ๋ฐ๊พธ๋ผ๋ ์ปดํ์ผ๋ฌ์ ๋ฉ์์ง๊ฐ ๋ฌ๋ค.
// Money ์ฝ๋class MoneyMoney times(int amount) { return null;}
Money์ ์คํผ๋ ์ด์ ์ด ๊ตฌํ์ฒด๋ฅผ ๊ฐ์ง๋๋ก ์ต์ํ์ times์ฝ๋๋ฅผ ์งฐ๋ค.
๋๋ฆฌ๊ณ ๋๋ ๋นจ๊ฐ๋ง๋(์๋ฌ๋ฉ์์ง)๊ฐ ๋จ๋๋ฐ, ๋ฉ์์ง๊ฐ ๋ญ๋ผ๊ณ ํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ๋ค.
// Money ์ฝ๋// ๊ฐ์ฒด ์ ๋ณด๋ฅผ ํ์ํด์ฃผ๋ ์คํธ๋งํจ์public String toString() { return amount + " " + currency}
์ด ์ฝ๋๋ฅผ ์ง ํ ํ ์คํธ๋ฅผ ๋๋ ค๋ณด๋, ์๋ฌ ๋ฉ์์ง๊ฐ ๋ค์๊ณผ ๊ฐ์ด ๋ฌ๋ค.
expected:<10 CHF> but was:<10 CHF>
๋ญ์ง? ๊ฐ์๊ฑด๋ฐ ๋ค๋ฅด๋ค๊ณ ? ์ดํด๋ณด๋ ํด๋์ค๊ฐ ๋ค๋ฅด๋จ๋ค. ์์ <10 CHF>๋ Franc์ธ๋ฐ, ์ค์ ๋ก ๋ค์ด๊ฐ ๊ฐ์ธ ๋ค์ <10 CHF>๋ Money๋๋ค.
// Franc ์ฝ๋Money times(int multiplier) { return new Money(amount * multiplier, currency);}
์๊น times()
๊ฐ Money๋ฅผ ๋ฐํํ๋๋ก ์ฝ๋๋ฅผ ์งฐ์ผ๋ ๋ค์ ๊ฑด ๋ง๋๋ฐ, ์์ Franc <10 CHF>๋ ์ด๋์ ๋์์๊น?
ํ
์คํธ์ฝ๋์์ ์ค๋ฅ๊ฐ ๋ด์ผ๋ ๋น๊ต์์ ์ค๋ฅ๊ฐ ๋ฌ์ํ
๋ฐ... ๊ทธ๋ ๋ค๋ฉด equals()
๋ฅผ ์ดํด๋ณด์.
// Money ์ฝ๋public boolean equals(Object object) { Money money = (Money) object; return amount = money.amount && getClass().equals(money.getClass());}
getClass()
๋ก ํด๋์ค๋ฅผ ๋น๊ตํจ์ผ๋ก์จ ํตํ๋ฅผ ๋น๊ตํ๋ค๋ ์ฐฉ๊ฐ์ ๋น ์ง ์ ์์ง๋ง, ์ค์ ๋ก๋ ๊ทธ๋ ์ง ์๋ค. Money(10, 'CHF')์ Franc(10, 'CHF')๋ ์ ์ธํ ํด๋์ค์ ์์น๋ง ๋ค๋ฅผ ๋ฟ์ด์ง. ๋ด๋ถ์ currency๋ 'CHF'๋ก ๊ฐ๋ค. ์ฆ ๊ฐ์ ํตํ์ธ ๊ฒ์ด๋ค. ๊ทธ๋ฐ๋ฐ ์์ ์ฝ๋๋ ํด๋์ค๋ฅผ ๋น๊ตํ๊ณ ์์ผ๋ฏ๋ก, ํด๋น ์ฝ๋๋ฅผ currency ๋น๊ต๋ก ๊ณ ์ณ์ผํ ๊ฒ์ด๋ค.
๊ทธ๋ผ ๋ฌธ์ ์ ์์ธ์ ํ์ ํ์ผ๋ ๋ฐ๋ก ๊ณ ์น ๊น?
๋ณด์์ ์ผ๋ก ๋ณด๋ฉด ๊ทธ๋ ๊ฒ ํ๋ฉด ์๋๋ค. ํ
์คํธ์ฝ๋๋ ๋นจ๊ฐ
๋ง๋์ธ ๊ฒฝ์ฐ์ ์ค์ ๋ชจ๋ธ ์ฝ๋๋ฅผ ๊ณ ์น์ง ์๋๋ค. ๋ถํ์ค์ฑ ์์ ๋ถํ์ค์ฑ์ ๋ง๋ถ์ด๋ ์
์ด๊ธฐ ๋๋ฌธ์ด๋ค. ์ค์ ๋ชจ๋ธ ์ฝ๋๋ฅผ ๊ฑด๋๋ฆฌ๋ ค๋ฉด ์์ธ์ ๋จผ์ ํ์
ํ๊ณ , ์ด๋ก
๋ง๋์์ ์์ํด์ผํ๋ค(๋จ๋จํ ๊ธฐ๋ฐ์์ ์์ํ๋ค๊ณ ์๊ฐํ์). ๋นจ๊ฐ
๋ง๋๋ฅผ ๋ณด๊ธฐ ์ง์ ์ฝ๋๋ก ๋์๊ฐ์.
// Franc ์ฝ๋Money times(int multiplier) { return new Franc(amount * multiplier, currency);}
๊ทธ๋ผ ๋ค์ ์ฌ๊ธฐ์ ์ฐ๋ฆฌ๊ฐ ํ์ ํ ๋ฌธ์ ์ -๋ค๋ฅธ ํด๋์ค๋ผ๋ currency๊ฐ ๊ฐ๋ค๋ฉด ๊ฐ์ ํตํ๋ก ์ทจ๊ธํด์ผํ๋ค๋ ๊ฒ-์ ๊ทธ๋๋ก ํ ์คํธ์ฝ๋๋ก ์ง๋ณธ๋ค.
public void testDifferentClassEquality() { assertTrue(new Money(10, "CHF").equals(new Franc(10, "CHF")));}
์์ ์ฝ๋๋ ์คํจํ๋ค. ์์ง ์ค์ ๋ชจ๋ธ ์ฝ๋๊ฐ currency๊ฐ ์๋ ํด๋์ค๋ฅผ ๋น๊ตํ๊ณ ์๊ธฐ ๋๋ฌธ์ด๋ค. ํ ์คํธ์ fail์ ํ์ธํ๊ณ ์ค์ ๋ชจ๋ธ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ๋ค.
// Money ์ฝ๋public boolean equals(Object object) { Money money = (Money) object; return amount = money.amount && currency().equals(money.currency());}
์ด์ ๋ ํ์ ํด๋์ค์์ ๋ฆฌํด๊ฐ์ ํด๋์ค๋ฅผ Money๋ก ๋ฐ๊พธ์ด๋ ์ ๋๋ก ๋์ํ ๊ฒ์ด๋ค.
// Franc ์ฝ๋Money times(int multiplier) { return new Money(amount * multiplier, currency);}// Dollar ์ฝ๋Money times(int multiplier) { return new Money(amount * multiplier, currency);}
๋ ๊ตฌํ์ด ๋์ผํด์ก์ผ๋, ์์ ํด๋์ค๋ก push up ํ ์ ์๋ค.
// Money ์ฝ๋Money times(int multiplier) { return new Money(amount * multiplier, currency);}
์ด์ ํ์ ํด๋์ค Franc์ Dollar์์ ํ๋ ๋ชจ๋ ์คํผ๋ ์ด์ ์ ์์ ํด๋์ค๋ก ๋์ด์ฌ๋ ธ์ผ๋, Franc์ Dollar๋ผ๋ ํ์ ํด๋์ค๋ค์ ์ถฉ๋ถํ ์ ๊ฑฐํ ์ ์๊ฒ ๋์๋ค.
โฆ 10(ํ์จ์ด 2:1์ผ ๊ฒฝ์ฐ)
โฆ10
โฆamount๋ฅผ private์ผ๋ก ๋ง๋ค๊ธฐ
โฆDollar ๋ถ์์ฉ?
โฆ Money ๋ฐ์ฌ๋ฆผ?
โฆequals()
โฆ hashCode()
โฆ Equal null
โฆ Equal object
โฆ5CHF * 2 = 10CHF
โฆ Dollar/Franc ์ค๋ณต
โฆ๊ณต์ฉ Equals
โฆ๊ณต์ฉ times
โฆFranc์ Dollar ๋น๊ตํ๊ธฐ
โฆํตํ?
โฆ testFrancMultiplication ์ ๊ฑฐ