Чтобы понять происхождение вопроса, давайте начнем с некоторого кода:
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
). что больше похоже на обходной путь, который может вызвать нежелательное поведение на дороге.
Итак, я начал думать, что, возможно, есть способ ограничить параметр generi c параметром-братом примерно так (псевдокод):
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