要了解问题的起源,让我们从一些代码开始:
protocol MyProtocol {
var val1: Int { get set }
}
struct StructA: MyProtocol {
var val1: Int
var structAVal: Int
}
struct StructB: MyProtocol {
var val1: Int
var structBVal: Int
var thirdProperty: Int
}
然后我有一个类型为异构数组的结构MyProtocol
:
struct Values {
var arr: [MyProtocol] = [StructA(val1: 0, structAVal: 0), StructB(val1: 0, structBVal: 0)]
}
如果我要使用以下方法更改其中一个值Values
:
struct Values {
var arr: [MyProtocol] = [StructA(val1: 0, structAVal: 0), StructB(val1: 0, structBVal: 0)]
mutating func set<T: MyProtocol>(at index: Int, _ newValue: T) {
arr[index] = newValue
}
}
那会很顺利。我面临的问题是,假设我想更改var thirdProperty: Int
中的structB
项目var arr: [MyProtocol]
,我将无法这样做mutating func set<T: MyProtocol>(at index: Int, _ newValue: T)
,因为它只知道MyProtocol
类型。
所以我解决这个问题的 2 美分是使用这样的闭包:
mutating func set<T: MyProtocol>(at index: Int, closure: (T?) -> (T)) {
arr[index] = closure(arr[index] as? T)
}
这样做的问题是,每次我调用这个方法时,我首先需要向下转换参数(从MyProtocol
到StructB
)。这似乎更像是一种解决方法,可能会在路上引起不受欢迎的行为。
所以我开始思考也许有一种方法可以将泛型参数限制为类似这样的兄弟参数(伪代码):
mutating func set<T: MyProtocol>(type: MyProtocol.Type, at index: Int, closure: (T?) -> (T)) where T == type {
arr[index] = closure(arr[index] as? T)
}
正如您所猜测的那样,它不会编译。
关于如何以更好的方式处理这个问题的任何想法。TIA