【发布时间】:2017-04-19 16:34:22
【问题描述】:
我遇到了一个问题。 考虑我有一个协议和两个实现它的类:
protocol Initiatable{
init()
}
class A: Initiatable{
required init() {}
}
class B: Initiatable{
required init() {}
}
然后在某个时候我正在创建一个数组并将其传递给函数:
var array = [A]()
func update(object: Any){
}
update(object: array)
从那个函数update 如果它满足另一个函数的条件,我想将object 传递给另一个函数:
func process<T: Initiatable>(array: T){
/* ... */
}
那么如何检查Any 类型的对象是实现Initiatable 协议的具体类的数组?我想写一些类似的东西
func update(object: Any){
if let array = object as Array<T: Initiatable>{
process(array: array)
}
}
但那是行不通的。代码如下:
func update(object: Any){
if let array = object as [Initiatable]{
process(array: array)
}
}
func process(array: [Initiatable]){ }
编译得很好,但这不是我想要的——process 函数应该接收Initiatable 的具体实现数组,所以在某些时候它可以使用:
func process<T: Initiatable>(array: [T]){
/* other code */
T.init()
}
那么有没有办法做到这一点?非常感谢您!
【问题讨论】:
-
我在处理泛型时也遇到过这类问题。是否有理由没有像
func update<T: Initiatable >update(object: [T])这样的第二版更新? -
一旦你打电话给
T.init(),你能用它做什么?没有您可以调用它的方法,那么process实际上可以做什么?你唯一知道的是它可以使用init()构造。标准库中不存在Initiatable是有原因的。这不是偶然的遗漏。 oleb.net/blog/2016/12/protocols-have-semantics 这里有很多令人担忧的模式(从传递Any开始)。即使你让它工作,这种通用/反射代码也往往非常脆弱。你想用它做什么? -
上面示例中的代码只是我正在使用的代码的简化。当然
Initiatable在我的代码中还有其他功能(并且名称也不同)