ajrlewis
ajrlewis

Reputation: 3058

Generics in protocols

I have a UnitDimension class given by:

class UnitDimension: {
    var symbol: String
    init(symbol: String) {
        self.symbol = symbol
    }
}

and a UnitVolume subclass of this class:

class UnitVolume: UnitDimension {
    static let liter = UnitVolume(symbol: "L")
}

I want to have a protocol UnitDimensionHandler that allows me to perform some simple functions. Firstly it must have an allUnits variable:

protocol UnitDimensionHandler: class {
    static var allUnits: [UnitDimension] { get }
}

Is it possible to have allUnits a generic type of array that must be a subclass of UnitDimension? I could then implement it in UnitVolume as follows:

extension UnitVolume: UnitDimensionHandler {
    static var allUnits: [UnitVolume] {
        return [liter]
    }
}

I then want to include a function that also allows me to use a generic subclass type that initiates a UnitDimension instance:

extension UnitDimensionHandler {
    static func unit(for symbol: String) -> UnitDimension? {
        return allUnits.first() { $0.symbol == symbol }
    }
}

such that UnitVolume.unit(for: "L") returns an optional UnitVolume rather than an optional UnitDimension.

Thanks for any help.

Upvotes: 1

Views: 55

Answers (1)

user28434'mstep
user28434'mstep

Reputation: 6600

Yes it is possible, using associatedtype:

protocol UnitDimensionHandler: class {
    // here we define `generic` type variable `Dimension`, and specify it do be descendant of `UnitDimension`
    associatedtype Dimension: UnitDimension

    // and use it here, instead of `UnitDimension`
    static var allUnits: [Dimension] { get }
}

And

extension UnitDimensionHandler {
    // same `UnitDimension` -> `Dimension` replacement
    static func unit(for symbol: String) -> Dimension? {
        return allUnits.first() { $0.symbol == symbol }
    }
}

Upvotes: 2

Related Questions