将遵循SQLObject协议的类型传入泛型函数时遇类型不兼容问题
解决Swift中
(Foo).Type不符合SQLObject类型的错误 嘿,这个问题我之前也踩过坑!其实核心就是元类型和实例类型的不匹配,听我给你掰扯清楚:
为啥会报错?
你写的storedObjects方法,参数要求是一个遵循SQLObject的实例对象(T: SQLObject),但你调用时传的Foo是一个元类型(也就是Foo.Type,代表类型本身)—— 元类型可不遵循你定义的SQLObject协议,协议是给实例对象制定的规则,所以编译器自然会报错啦。
怎么改?
我们只需要把方法改成接受元类型参数就行,这样就能正确接收Foo这个类型标识了:
第一步:调整DataManager的方法
把方法的参数类型从T改成T.Type,泛型约束保持不变:
class DataManager { static let shared = DataManager() // 这里把参数类型改成T.Type func storedObjects<T: SQLObject>(_ type: T.Type) throws -> [T] { // 你的原有查询逻辑完全可以复用,因为现在可以通过T访问协议要求的静态属性和初始化方法 // 举个参考实现的例子: let tableName = T.tableName guard let resultSet = try? database.executeQuery("SELECT * FROM \(tableName)", values: nil) else { throw DatabaseError.queryFailed } var objects = [T]() while resultSet.next() { let object = try T.init(result: resultSet) objects.append(object) } return objects } }
第二步:正确调用方法
现在你只需要稍微调整下调用代码,加上.self明确传入元类型(或者让Swift自动推断):
// 写法1:明确传入元类型 let foos = try DataManager.shared.storedObjects(Foo.self) // 写法2:指定变量类型,让Swift自动推断(更简洁) let foos: [Foo] = try DataManager.shared.storedObjects(Foo.self)
可选优化:让调用更简洁
如果你觉得每次写.self麻烦,可以给DataManager加个扩展,实现一个无参数的版本,利用Swift的类型推断:
extension DataManager { func storedObjects<T: SQLObject>() throws -> [T] { return try storedObjects(T.self) } }
这样调用起来就更清爽了:
let foos: [Foo] = try DataManager.shared.storedObjects()
内容的提问来源于stack exchange,提问作者Moose
相关产品推荐
相关产品推荐

