Я постараюсь продемонстрировать, что я имею в виду, на примере.
Скажем, у меня есть этот протокол:
protocol P {}
И эти типы, которые ему соответствуют:
struct S1 : P {}
struct S2 : P {}
И, наконец, этот универсальный метод, который принимает один параметр любого типа, соответствующего протоколу P:
func f<T>(type: T.Type) where T : P {
// ...
}
Теперь нет проблем с переходом S1.self или S2.self в f.
f(type: S1.self) // No problem!
f(type: S2.self) // No problem!
Но если я хочу добавить S1.self и S2.self в массив
let types: [P.Type] = [S1.self, S2.self]
Я не смогу перейти к f типу из этого массива.
f(type: types[0]) // ERROR: Cannot invoke 'f' with an argument list of type '(type: P.Type)'
Я не понимаю, что я делаю неправильно. Любая помощь будет принята с благодарностью.





Swift должен уметь определять тип универсальной функции во время компиляции. Вызов универсальной функции превращается в явный вызов, обрабатывающий только один тип. Вы пытаетесь превратить это в решение во время выполнения, которое не сработает.
Если вы хотите вызвать f(type:) со значением из вашего массива, вам нужно будет установить его тип перед выполнением общего вызова.
Например, это можно сделать с помощью switch:
switch types[0] {
case let type as S1.Type:
f(type: type)
case let type as S2.Type:
f(type: type)
default:
break
}
или с if case let:
if case let type as S1.Type = types[0] {
f(type: type)
}
Спасибо! В этом есть смысл.
Это невозможно для аргументов функции. Потому что использование универсального T: P похоже на: я не знаю, какой у него тип, но он должен соответствовать P. Компилятор выводит тип, когда вы передаете аргумент функции.
Таким образом, проблема заключается в множество дженериков, которые вы использовали. Он может заполнять массив, но когда вы вызываете некоторый индекс массива, он возвращает Неизвестный тип, соответствующий P. Так это не может вывести общий тип T от него
Итак, вы должны сказать себе, какой это тип:
f(type: types[0] as! S1.Type)
И если вы не знаете, какой это тип, вы можете проверить это перед вызовом функции:
switch types[0] {
case is S1.Type: f(type: types[0] as! S1.Type)
case is S2.Type: f(type: types[0] as! S2.Type)
default: break
}
Спасибо! В этом есть смысл.
Это связано с Протокол не соответствует самому себе? и не связано с массивами.
let t: P.Type = S1.self ; f(type: t)также не будет компилятором.