我有一个协议(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/