Reputation: 39253
This works
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)
}
}
This seems to violate DRY. It is possible to refer to Die
indirectly in the yahtzeeDice
function?
Upvotes: 1
Views: 573
Reputation: 73186
First of all, note that the repeating initializer of the [Die]
array in your question will instantiate a single Die
instance, thereafter repeat the reference to this instance 5 times in the array (since Die
is reference type). I.e., all members of [Die]
in your example hold a strong reference to the same underlying Die
instance. So remember to avoid the repeating array initializer if you use reference types.
Now, you could construct a protocol that provides a default implementation of a blueprinted static
dice supplier method, which supplies an array of Self
instances, using some other blueprinted initializer.
// 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) }
}
}
If you mark your Dice
class final
(why final
? refer to the linked Q&A below), you'll have access to this default implementation directly when conforming to the DiceFactory
protocol.
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 */
But the again, do you have a good reason not to explicitly type out Die
?
See also:
Upvotes: 1