Обобщения в протоколах - PullRequest
0 голосов
/ 04 января 2019

У меня есть UnitDimension класс, заданный:

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

и UnitVolume подкласс этого класса:

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

Я хочу иметь протокол UnitDimensionHandler, который позволяет мне выполнять некоторые простые функции. Во-первых, она должна иметь переменную allUnits:

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

Возможно ли иметь allUnits универсальный тип массива, который должен быть подклассом UnitDimension? Затем я мог бы реализовать его в UnitVolume следующим образом:

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

Затем я хочу включить функцию, которая также позволяет мне использовать общий тип подкласса, который инициирует экземпляр UnitDimension:

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

такой, что UnitVolume.unit(for: "L") возвращает необязательный UnitVolume вместо необязательного UnitDimension.

Спасибо за любую помощь.

1 Ответ

0 голосов
/ 04 января 2019

Да, это возможно, используя 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 }
}

И

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