通貨(Currency)の概念を導入する。
①MoneyクラスにCurrencyの抽象Method入れる。
②やっぱ親クラスにプロパティ入れよ。
③コンストラクタでCurrencyの値入れよ。
④timesMethodは自分のコンストラクタ呼び出すんじゃなくてファクトリメソッド使おう!
playground.swift
import UIKit
var moneytest = MoneyTest()
moneytest.TestMultiplication()
moneytest.TestEquality()
moneytest.TestFrancMultiplication()
class MoneyTest{
init(){}
func TestMultiplication(){
var five:Money = Money.dollar(5)
assert(Money.dollar(10) == five.times(2))
assert(Money.dollar(15) == five.times(3))
}
func TestEquality(){
assert(Money.dollar(5) == Money.dollar(5))
assert(Money.dollar(6) == Money.dollar(6))
assert(Money.franc(5) == Money.franc(5))
assert(Money.franc(6) == Money.franc(6))
assert(Money.franc(6) != Money.franc(3))
assert(Money.franc(6) != Money.dollar(6))
}
func TestFrancMultiplication(){
var five = Money.franc(5)
assert(Money.franc(10) == five.times(2))
assert(Money.franc(15) == five.times(3))
}
}
///親クラス
class Money :Equatable{
var amount:Int
var currency:String
init(_ amount:Int,_ currency:String){
self.amount = amount
self.currency = currency
}
static func == (lhs: Money, rhs: Money) -> Bool {
return lhs.amount == rhs.amount && type(of: lhs) == type(of: rhs)
}
func currency()-> String{
return currency
}
func times(_ multiplire:Int) -> Money{
return Money(amount , currency)
}
static func dollar(_ amount:Int) -> Dollar{
return Dollar(amount,"USD")
}
static func franc(_ amount:Int) -> Franc{
return Franc(amount,"CHF")
}
}
///Dollar子クラス
class Dollar:Money {
override init(_ amount:Int,_ currency:String){
super.init(_ :amount , _ :currency)
self.amount = amount
self.currency = currency
}
override func times(_ multiplire:Int) -> Dollar{
return Money.dollar(amount * multiplire)
}
}
///Franc子クラス
class Franc:Money {
override init(_ amount:Int, _ currency:String){
super.init(_ :amount , _ :currency)
self.amount = amount
self.currency = currency
}
override func times(_ multiplire:Int) -> Franc{
return Money.franc(amount * multiplire)
}
}
振り返り
・大きめの設計変更にのめり込みそうになったので、その前に手前にある小さな変更に着手した。
・差異を呼び出し側(FactoryMethod側)に移動することによって、2つのサブクラスのコンストラクタを近づけていった。
・リファクタリングの途中で少し寄り道して、timesメソッドの中でFactoryMethodを使うように変更した。
・Francに行ったリファクタリングをDollarにも同様に、今度は大きい歩幅で一気に適用した。
・完全に同じ内容になった2つのコンストラクタを親クラスに引き上げた。