我将尝试通过示例来说明我的意思。
说我有这个协议:
#!/bin/bash
set -e
echo one
echo two
cd x
echo three
符合这些类型的这些类型:
protocol P {}
最后,这种通用方法接受一个参数,该参数可以是符合协议P的任何类型:
struct S1 : P {}
struct S2 : 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
我不明白我在做什么错。任何帮助将不胜感激。
答案 0 :(得分:1)
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)
}
答案 1 :(得分:1)
这对于函数参数是不可能的。因为使用通用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
}