2017-01-15 36 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