【发布时间】:2021-03-01 19:40:01
【问题描述】:
鉴于以下情况,这将引发关于协议无法遵守自身的编译时错误,并且只有 struct/enum 可以遵守协议。这似乎违背了能够在泛型中使用协议的目的。我试图理解为什么这不起作用,但如果我删除泛型并将协议放在“Z”所在的位置,一切都很好。这似乎与应该允许使用的协议和泛型是对立的。
**为清楚问题而编辑:我需要采用可以转换为 [String:MyProtocol] 字典的 Any 类型并将其传递给方法 printEm。 printEm 必须使用泛型,因为它将实例化 Z 类的实例。
protocol MyProtocol {
init()
var whoAmI:String { get }
}
func genericPassing(unknownThing:Any) {
let knownThing = unknownThing as? [String:MyProtocol]
if(knownThing != nil){
self.printEm(knownThing)
}
}
func printEm<Z:MyProtocol>(theThings:[String:Z]) {
let zCollection:[Z] = []
for thing in theThings {
print(thing.whoAmI)
zCollection.append(Z())
}
}
**编辑 printEm 以说明为什么需要泛型。
** 编辑更复杂的代码。两个主要要求是使用泛型调用 Z() 以及能够接受 Any 并以某种方式对其进行类型检查和/或强制转换,以便可以在泛型方法中使用它。
private func mergeUpdates<Z:RemoteDataSyncable>(source:inout Z, updates:[WritableKeyPath<Z, Any>:Any]) throws {
for key in updates.keys {
let value = updates[key]!
let valueDict = value as? [String:[WritableKeyPath<RemoteDataSyncable, Any>:Any]]
if(valueDict != nil) {
var currentValueArray = source[keyPath: key] as? [RemoteDataSyncable]
if(currentValueArray != nil) {
self.mergeUpdates(source: ¤tValueArray!, updates: valueDict!)
}
else {
throw SyncError.TypeError
}
}
else {
source[keyPath: key] = value
}
}
}
private func mergeUpdates<Z:RemoteDataSyncable>(source:inout [Z], updates:[String:[WritableKeyPath<Z,Any>:Any]]) {
for key in updates.keys {
var currentObject = source.first { syncable -> Bool in
return syncable.identifier == key
}
if(currentObject != nil) {
try! self.mergeUpdates(source: ¤tObject!, updates: updates[key]!)
}
else {
var newSyncable = Z()
try! self.mergeUpdates(source: &newSyncable, updates: updates[key]!)
source.append(newSyncable)
}
}
}
【问题讨论】:
-
(1) 你想做什么? (2) 问题是什么?
-
@matt 我需要上面的这两种方法不会引发编译错误。更具体地说,我需要能够获取具有通用协议的字典并将其传递给通用方法。所以,我需要能够将 [String:MyProtocol] 传递给 func printEm
(theThigns; [String:Z]) 以便我可以做 theThings["key"].whoAmI 以及 Z() .除此之外,我想了解为什么当前的实现不起作用,因为它似乎是泛型和协议应该能够在许多其他语言中处理和执行的本质。 -
正如错误所说,协议不符合自己,但您不需要它们。你的通用没有做任何事情。摆脱它。这应该是
func printEm(theThings: [String: MyProtocol])。 -
"将 [String:MyProtocol] 传递给 func printEm
(theThigns; [String:Z])" - 不,这不是 Z 的意思。 Z:MyProtocol表示“MyProtocol 采用者”。您将通过[String:What]符合 MyProtocol 的内容。 -
是的,我知道我能做到,但那行不通。我将在上面进行调整以说明为什么这在我的特定情况下不起作用。有没有办法获得用于
uknownThings的泛型并将其作为Z传递?