ios - 在类型化数组中存储符合泛型协议(protocol)的对象

标签 ios swift generics protocols generic-collections

我有一个协议(protocol):

protocol Adjustable: Equatable {
    associatedtype T
    var id: String { get set }
    var value: T { get set }
    init(id: String, value: T)
}

以及符合它的结构:

struct Adjustment: Adjustable {
    static func == (lhs: Adjustment, rhs: Adjustment) -> Bool {
        return lhs.id == rhs.id
    }

    typealias T = CGFloat
    var id: String
    var value: T
}

我正在构建一个包装类,其行为类似于 Set 来处理这些属性的有序列表:

struct AdjustmentSet {
    var adjustmentSet: [Adjustable] = []
    func contains<T: Adjustable>(_ item: T) -> Bool {
        return adjustmentSet.filter({ $0.id == item.id }).first != nil
    }
}

let brightness = Adjustment(id: "Brightness", value: 0)

let set = AdjustmentSet()
print(set.contains(brightness))

但这当然行不通,错误是:

error: protocol 'Adjustable' can only be used as a generic constraint because it has Self or associated type requirements var adjustmentSet: [Adjustable] = []

环顾四周,一开始我以为是因为协议(protocol)不符合Equatable,后来我加了,还是不行(或者我做错了)。

此外,我希望能够在这里使用泛型,这样我就可以做类似的事情:

struct Adjustment<T>: Adjustable {
    static func == (lhs: Adjustment, rhs: Adjustment) -> Bool {
        return lhs.id == rhs.id
    }

    var id: String
    var value: T
}

let brightness = Adjustment<CGFloat>(id: "Brightness", value: 0)

或者:

struct FloatAdjustment: Adjustable {
    static func == (lhs: Adjustment, rhs: Adjustment) -> Bool {
        return lhs.id == rhs.id
    }
    typealias T = CGFloat
    var id: String
    var value: T
}

let brightness = FloatAdjustment(id: "Brightness", value: 0)

并且仍然能够存储 [Adjustable] 类型的数组,因此最终我可以这样做:

var set = AdjustmentSet()
if set.contains(.brightness) {
    // Do something!
}

或者

var brightness = ...
brightness.value = 1.5
set.append(.brightness)

最佳答案

您不能拥有 Adjustable 类型的项目数组,因为 Adjustable 实际上不是一种类型。它是描述一组类型的蓝图,每个类型对应 T 的每个可能值。

要解决这个问题,您需要使用类型橡皮擦 https://medium.com/dunnhumby-data-science-engineering/swift-associated-type-design-patterns-6c56c5b0a73a

关于ios - 在类型化数组中存储符合泛型协议(protocol)的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54836085/

相关文章:

iOS 11 Core NFC - 没有这样的模块 'Core NFC'

ios - UITableViewCell 在不改变其内容布局的情况下调整高度

iOS:特定 View Controller 类的 didReceiveRemoteNotification

ios - 在 Swift 中将拾取的图像从 UIImagePicker 设置为 UIImageView

ios - Realm Swift 如何将观察者添加到对象类型(无)

swift - 您可以强制使用两种类型的泛型来确保这些类型不相同吗?

ios - Xcode 在不使用 Storyboard时无法在捆绑 NSBundle 中找到名为 'Main' 的 Storyboard

ios - UITableView插入行动画与自定义单元格不一致

swift - 使用通用 where 条件和指定参数类型有什么区别?

java - 有没有办法定义一个通用方法来检查 null 然后创建对象?