使用泛型将符合协议的对象和泛型存储在类型数组中 [英] Storing objects conforming to a protocol with generics in a typed array
问题描述
我有一个协议:
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
,以处理这些属性的有序列表:
And I'm building a wrapper class that behaves like a Set
to handle an ordered list of these properties:
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))
但是那当然是行不通的,出现以下错误:
But that of course doesn't work, erroring with:
错误:协议可调整"只能用作一般约束,因为它具有自我"或相关联的类型要求 var AdjustmentSet:[可调] = []
error: protocol 'Adjustable' can only be used as a generic constraint because it has Self or associated type requirements var adjustmentSet: [Adjustable] = []
环顾四周,我起初以为是因为该协议不符合Equatable
,但是后来我添加了它,但它仍然不起作用(或者我做错了).
Looking around, I thought at first this was because the protocol doesn't conform to Equatable
, but then I added it, and it still doesn't work (or I did it wrong).
此外,我希望能够在此处使用通用名称,以便可以执行以下操作:
Moreover, I would like to be able to use a generic here, so that I can do something like:
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]
类型的数组,以便最终我可以做到:
And still be able to store an array of [Adjustable]
types, so that eventually I can do:
var set = AdjustmentSet()
if set.contains(.brightness) {
// Do something!
}
或
var brightness = ...
brightness.value = 1.5
set.append(.brightness)
推荐答案
您不能拥有类型为Adjustable
的项目数组,因为Adjustable
并不是真正的类型.这是一张蓝图,描述了一组类型,每个T
的可能值中的一个.
You can't have an array of items of type Adjustable
, because Adjustable
isn't really a type. It's a blue print that describes a set of types, one per every possible value of T
.
要解决此问题,您需要使用类型橡皮擦 https://medium.com/dunnhumby-data-science-engineering/swift-associated-type-design-patterns-6c56c5b0a73a
To get around this, you need to use a type eraser https://medium.com/dunnhumby-data-science-engineering/swift-associated-type-design-patterns-6c56c5b0a73a
这篇关于使用泛型将符合协议的对象和泛型存储在类型数组中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!