Swift:运行时泛型类型推断
看到奇怪的泛型行为,这导致我相信我错过了我理解中的某些东西。Swift:运行时泛型类型推断
我正在使用以下方法循环抛出JSON响应并调用泛型方法。 User
,Card
和Ecard
全部来自IDObject
继承,这反过来从Object
(一类域)继承
let props:[(label:String, type:IDObject.Type)] = [
(label: "deletedUsers", type: User.self),
(label: "deletedCards", type: Card.self),
(label: "deletedECards", type: Ecard.self)
]
for prop in props {
if let ids = json[prop.label].arrayObject as? [Int], ids.count > 0 {
DataManager.shared.delete(prop.type, ids: ids)
}
}
func delete<T:IDObject>(_ type:T.Type, ids:[Int]) {
guard ids.count > 0 else { return }
if let objectsToDelete = objects(type, where: NSPredicate(format: "identifier IN %@", ids)) {
delete(objectsToDelete)
}
}
func delete<T:Object>(_ objects:Results<T>) {
guard objects.count > 0 else { return }
do {
let realm = try Realm()
try realm.write {
realm.delete(objects)
}
} catch {
print(error)
}
}
的delete(_ type:T.Type, ids:[Int])
功能不能推断泛型类型这种方式。
但是,展开for prop in props
循环按预期工作。
if let userIds = json["deletedUsers"].arrayObject as? [Int], userIds.count > 0 {
DataManager.shared.delete(User.self, ids: userIds)
}
不要只泛型在编译的时候工作,或者是有没有办法在运行时动态处理呢?
泛型在编译时被评估并被分配一个具体的类型。没有“运行时类型推断”这样的东西。
我想你想的主要变化是:
func delete(_ type:IDObject.Type, ids:[Int]) {
你不想专注于type
这个功能,你只是想通过type
。
不清楚objects(_:where:)
返回什么,所以这可能会破坏您的delete
方法。您可能需要使它不那么具体:
func delete(_ objects:Results<Object>) {
(这是不是子类型的灵丹妙药;我假设objects(_:where:)
恰好返回Results<Object>
)
我认为通过“在运行时键入推论”他意味着类似[this](http://*.com/a/30945263/5175709)阅读**协议可以选择静态或动态调度。**他基本上是指静态与动态调度。 – Honey
我可能在这里错过了一些东西,但我没有看到如何改变'type'参数的静态类型将会改变OP代码的运行时行为(考虑到当他调用delete时(假设它实际上是DataManager.shared .delete'),'T'已被推断为'IDObject')。另请注意,泛型仅作为编译器优化专用。 – Hamish
它可能已经被推断为'IDObject',但专业上它是最好的混乱,因为读者可能认为更多的正在发生的事情(这是很难测试,因为此代码不能编译)。 “专业化”并不一定意味着编译器编写了一个独特的函数版本。 '阵列
究竟你“的意思*了'删除'函数不能通过这种方式推断泛型*“?你得到一个编译器错误? (如果是的话,在哪里?)你错过了'DataManager.shared.delete(prop.type,ids:ids')的右括号,除非你用单个参数重载'delete',否则不能调用它一个参数('delete(objectsToDelete)')。请你提供一个[mcve],包括预期的行为和实际行为? – Hamish
@Hamish整个代码库非常大,我不能随意分享它我已经在这里大量地编辑了它,并且我已经修复了缺失的右括号,'delete'确实被重载了 - 'delete(:)'方法需要一个'Results
你不需要共享整个代码库 - 只有一个最小的自包含的例子,重现相同的问题。是' DataManager.shared.delete'应该引用'delete(_:ids:)'?什么是对象(_:where:)'return?(你没有甚至必须显示功能,只是模拟一个功能,重现相同的问题)。 “ids”甚至与问题有关吗? (如果没有,请将其删除)。 – Hamish