考虑以下测试用例,其中包含一个'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初始化器.我希望能够将下载对象添加到队列中,但由于下载对象的通用特性,我无法想到将它们添加到队列的任何方式.
我最近回想起这个问题需要一个更好的答案\xe2\x80\x94,因为我正在执行一些重构\xe2\x80\x94,并认为拥有该类的通用属性将非常有用,这当然意味着类本身也必须是通用的。
\n\n我不确定为什么我以前没有想到这一点,但我可以简单地创建一个反映该类的非泛型方法的协议。使用我最初在问题中使用的示例,我可以创建一个FactoryProtocol类似的示例:
protocol FactoryProtocol {\n func callResultHandler()\n}\nRun Code Online (Sandbox Code Playgroud)\n\n使类符合它:
\n\nclass Factory<T : Defaultable>: FactoryProtocol\nRun Code Online (Sandbox Code Playgroud)\n\n然后在定义数组时使用协议而不是类:
\n\nvar factoryQueue = [FactoryProtocol]()\nRun Code Online (Sandbox Code Playgroud)\n\n这允许我向数组添加任何类型的专用方法Factory,并根据需要与非通用方法进行交互。
| 归档时间: |
|
| 查看次数: |
110 次 |
| 最近记录: |