SwiftでTDD写経 第8章 実装を隠す



●timesが似ているので統一してしまいたい。
 →返すオブジェクトの型をMoney型にしてしまおう

```playground.swift

///Dollar子クラス
class Dollar:Money {
    override init(_ amount:Int){
        super.init(_ :amount)
        self.amount = amount
    }
    
    func times(_ multiplire:Int)  -> Money{
        return Dollar(amount * multiplire)
    }
}

///Franc子クラス
class Franc:Money {
    override init(_ amount:Int){
        super.init(_ :amount)
        self.amount = amount
    }
    
    func times(_ multiplire:Int)  -> Franc({
        return Franc(amount * multiplire)
    }
}

```

●サブクラスのDollarとFrancは大した仕事してないから消してしまおう。
　　→ちょっと複雑だから小さく変更していく。子クラスの参照から消し去る。
　　　　ここでfactory Methodを適用するぜ！
　　　（要はMoneyクラスが工場で、DollarやFrancはその工場から作られるアンパンマンの頭だ！（パンな））

```playground.swift
　class MoneyTest{
    init(){}

    func TestMultiplication(){
        var five = Money.Dollar(5)
        assert(Dollar(10) == five.times(2))
        assert(Dollar(15) == five.times(3))
    }

    func TestFrancMultiplication(){
        var five = Money.Franc(5)
        assert(Franc(10) == five.times(2))
        assert(Franc(15) == five.times(3))
    }
}

```

```playground.swift

///親クラス
class Money :Equatable{
    var amount:Int
    init(_ amount:Int){
        self.amount = amount
    }
    static func == (lhs: Money, rhs: Money) -> Bool {
        return lhs.amount == rhs.amount && type(of: lhs) == type(of: rhs)
    }

    static func dollar(_ amount:Int) -> Dollar{
        return Dollar(amount)
    }

}


```


Javaでいうabstractが、swiftではprotocolを使えば表現できるんですが今回は見送り。
（Swiftは抽象クラスをサポートしてません。）

```playground.swift

import UIKit


var moneytest = MoneyTest()

moneytest.TestMultiplication()
moneytest.TestEquality()
moneytest.TestFrancMultiplication()

class MoneyTest{
    init(){}

    func TestMultiplication(){
        var five: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 = Franc(5)
        assert(Money.franc(10) == five.times(2))
        assert(Money.franc(15) == five.times(3))
    }
}
///親クラス
class Money :Equatable{
    var amount:Int
    init(_ amount:Int){
        self.amount = amount
    }
    
    static func == (lhs: Money, rhs: Money) -> Bool {
        return lhs.amount == rhs.amount && type(of: lhs) == type(of: rhs)
    }
    
    func times(_ multiplire:Int)  -> Money{
        return Money(amount * multiplire)
    }
    
    static func dollar(_ amount:Int) -> Dollar{
        return Dollar(amount)
    }
    
    static func franc(_ amount:Int) -> Franc{
        return Franc(amount)
    }
    
}

///Dollar子クラス
class Dollar:Money {
    override init(_ amount:Int){
        super.init(_ :amount)
        self.amount = amount
    }
    override func times(_ multiplire:Int)  -> Money{
        return Dollar(amount * multiplire)
    }
}


///Franc子クラス
class Franc:Money {
    override init(_ amount:Int){
        super.init(_ :amount)
        self.amount = amount
    }
    override func times(_ multiplire:Int)  -> Money{
        return Franc(amount * multiplire)
    }
}


```