2017-01-15 38 views
1

的`型這工作初始化self`

class Die { 
    let faces: Int 

    required init(faces: Int) { 
     self.faces = faces 
    } 

    func yahtzeeDice() -> [Die] { 
     return [Die](repeating: type(of: self).init(faces: 6), count: 5) 
    } 
} 

這似乎違背了DRY。在yahtzeeDice函數中可以間接引用Die

+1

你談論'[模具]''中yahtzeeDice()'或身體的方法簽名?後者可以用'Array'替代,因爲可以推斷出Die的元素類型。 – Hamish

+1

無關:爲什麼'yahtzeeDice()'是一個實例方法?你可以把它變成一個'static' /'class'方法,只需使用'self'而不是'type(of:self)'。 – Hamish

+0

你不能在簽名中使用'[Self]',因爲數組是一個結構體,如果'A:B'那麼'[A]'和'[B]'仍然是不相關的類型。 – Sulthan

回答

1

首先,請注意,在您的問題[Die]陣列的重複初始化將實例單個Die例如,此後在陣列中重複參考在此實例5倍(因爲Die是引用類型)。也就是說,在你的例子中[Die]的所有成員都強烈地引用了相同的底層Die實例。因此,如果使用引用類型,請記住避免重複數組初始值設定項。現在


,可以構建提供blueprinted static骰子供應商的方法,其提供Self實例的數組,使用一些其他blueprinted初始化的默認實現的協議。

// the 'class' requirement not strictly needed here, but it holds semantic 
// value to explain the 'map' call rather than using array:s 'repeating' 
// initializer in in the default implementation below 
protocol DiceFactory: class { 
    init(faces: Int, id: Int) 
    static func dice(_ n: Int) -> [Self] 
} 
extension DiceFactory { 
    static func dice(_ n: Int) -> [Self] { 
     return (1...n).map { Self.init(faces: 6, id: $0) } 
    } 
} 

如果您標記您的Dicefinal(爲什麼final?參考鏈接Q &下方的),你符合DiceFactory協議時,有機會獲得這個默認實現直接。

final class Die: DiceFactory { 
    let id: Int 
    let faces: Int 

    init(faces: Int, id: Int) { 
     self.faces = faces 
     self.id = id 
    } 
} 

let myDice = Die.dice(5) 
myDice.forEach { print($0, $0.id) } 
    /* Die 1 
     Die 2 
     Die 3 
     Die 4 
     Die 5 */ 

但是,你有沒有明確輸出Die的好理由?

參見:

+0

一個小改進,你可以使用'(1 ... n).map {Self.init(...)}'生成數組。 – Sulthan

+0

@Sulthan謝謝! – dfri

+1

請注意,使用'Array(重複:count:)'*可能是故意的,因爲'Die'實例是不可變的(可能OP只是使用一個類來繼承 - 如果情況並非如此,那麼它應該肯定是一個'struct')。 – Hamish