从类型数组将类型传递给泛型方法

时间:2019-07-08 12:22:29

标签: swift generics

我将尝试通过示例来说明我的意思。

说我有这个协议:

#!/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

我不明白我在做什么错。任何帮助将不胜感激。

2 个答案:

答案 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
}