是否可以拥有一个实例数组,这些实例采用通用参数而不知道(或关心)参数是什么?

Rob*_*ert 5 generics swift

考虑以下测试用例,其中包含一个'factory'类,它可以调用它包含的闭包,提供一些'defaultaultable'类型的新实例:

protocol Defaultable {
    init()
}

extension Int:    Defaultable { }
extension Double: Defaultable { }
extension String: Defaultable { }

class Factory<T : Defaultable> {
    let resultHandler: (T) -> ()

    init(resultHandler: (T) -> ()) {
        self.resultHandler = resultHandler
    }

    func callResultHandler() {
        resultHandler(T.init())
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,当我单独使用它时,这很好用,我可以跟踪泛型类型:

// Create Int factory variant...
let integerFactory = Factory(resultHandler: { (i: Int) in print("The default integer is \(i)") })

// Call factory variant...
integerFactory.callResultHandler()
Run Code Online (Sandbox Code Playgroud)

不幸的是,如果我想以一种无法跟踪泛型类型的方式使用工厂,它就不能很好地工作:

// Create a queue of factories of some unknown generic type...
var factoryQueue = [Factory]()

// Add factories to the queue...
factoryQueue.append(integerFactory)
factoryQueue.append(doubleFactory)
factoryQueue.append(stringFactory)

// Call the handler for each factory...
for factory in factoryQueue {
    factory.callResultHandler()
}
Run Code Online (Sandbox Code Playgroud)

我理解我得到的错误(通用参数'T'无法推断),但我不明白为什么我不能这样做,因为当我与数组交互时,我不需要知道什么是通用的参数是(我不与Factory实例中的任何通用事物交互).有什么方法可以实现上述目标吗?

请注意,以上是我正在尝试做的简化示例; 实际上我正在设计一个下载管理器,它可以使用泛型来推断我想要的文件类型(JSON,图像等); 该协议实际上包含一个init(data:) throws初始化器.我希望能够将下载对象添加到队列中,但由于下载对象的通用特性,我无法想到将它们添加到队列的任何方式.

Rob*_*ert 2

我最近回想起这个问题需要一个更好的答案\xe2\x80\x94,因为我正在执行一些重构\xe2\x80\x94,并认为拥有该类的通用属性将非常有用,这当然意味着类本身也必须是通用的。

\n\n

我不确定为什么我以前没有想到这一点,但我可以简单地创建一个反映该类的非泛型方法的协议。使用我最初在问题中使用的示例,我可以创建一个FactoryProtocol类似的示例:

\n\n
protocol FactoryProtocol {\n    func callResultHandler()\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

使类符合它:

\n\n
class Factory<T : Defaultable>: FactoryProtocol\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后在定义数组时使用协议而不是类:

\n\n
var factoryQueue = [FactoryProtocol]()\n
Run Code Online (Sandbox Code Playgroud)\n\n

这允许我向数组添加任何类型的专用方法Factory,并根据需要与非通用方法进行交互。

\n