如何利用泛型将自定义对象转换为指定结构的Dictionary?
嘿,这个问题挺典型的——你现在的困惑其实是对泛型的「约束逻辑」理解有点偏差,咱们一步步捋清楚,完全能实现需求的!
首先得说清楚:你现在写的无约束泛型T,编译器根本不知道它有idCustomer或者idSupplier这些属性,自然没法直接访问。泛型的核心是对符合特定约束的类型执行通用操作,所以咱们得给T加个「规矩」,让Customer和Supplier都遵守同一个接口,这样泛型方法就能统一调用属性了。
第一步:定义统一协议
先写一个协议,规定所有要转字典的类型必须暴露统一的id和title属性:
protocol DictConvertible { // 统一的ID属性 var unifiedID: Int { get } // 统一的标题属性 var unifiedTitle: String? { get } }
第二步:让对象遵循协议
给Customer和Supplier写扩展,把各自的属性映射到协议的统一属性上:
extension Customer: DictConvertible { var unifiedID: Int { idCustomer } var unifiedTitle: String? { name } } extension Supplier: DictConvertible { var unifiedID: Int { idSupplier } var unifiedTitle: String? { name } }
第三步:改造泛型方法
现在给泛型T加上DictConvertible约束,这样就能安全访问统一属性了。另外注意:你原来的方法参数是数组[T],但返回值是单个[String: Any],这明显不对——应该返回字典数组[[String: Any]]才符合逻辑,所以我帮你修正了:
func convertToDictArray<T: DictConvertible>(values: [T]) -> [[String: Any]] { return values.map { item in [ "id": item.unifiedID, "title": item.unifiedTitle ?? "" // 这里可以根据需求处理nil,比如保留nil就写item.unifiedTitle ] } }
额外说明:为什么不用反射?
可能有人会想到用Mirror反射来读取属性,但反射不仅性能差,还完全失去了类型安全——万一哪天你改了属性名,编译器不会给你报错,只会在运行时出问题。用协议的方式既优雅又安全,是Swift里处理这类问题的标准做法。
现在你就可以放心调用了:
let customers = [Customer(idCustomer: 1, name: "张三"), Customer(idCustomer: 2, name: "李四")] let suppliers = [Supplier(idSupplier: 100, name: "XX供应商")] let customerDicts = convertToDictArray(values: customers) let supplierDicts = convertToDictArray(values: suppliers)
内容的提问来源于stack exchange,提问作者Ludovic
相关产品推荐
相关产品推荐

