【发布时间】:2019-02-22 22:29:56
【问题描述】:
我有一个协议:
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))
但这当然行不通,会报错:
错误:协议 'Adjustable' 只能用作通用约束,因为它具有 Self 或关联的类型要求 var 调整集:[可调整] = []
看了一圈,一开始以为是协议不符合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)
【问题讨论】:
标签: ios swift generics protocols generic-collections