William Entriken
William Entriken

Reputation: 39253

Initializing type of `self`

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

Answers (1)

dfrib
dfrib

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

Related Questions