无共享协议变量时,结构一致名称不同的结构体能否等价访问?
解决方案:处理自动生成的重复结构体
这确实是自动生成代码常碰到的头疼事儿——明明逻辑上是同一个类型,却被拆成了名字不同但结构完全一致的两个结构体。既然没法修改生成的代码,咱们可以用下面几种方式来抹平这种差异,让代码更简洁易维护:
1. 快速统一:类型别名(Type Alias)
如果只是想在代码里用一个统一的名字来指代,最简单的方式就是给其中一个结构体起别名:
typealias Place = FromPlace
之后你就可以在自己的代码里统一用Place来代替FromPlace了。不过这个方法有局限:只能统一单个类型,要是需要同时处理FromPlace和ToPlace,就没法满足需求了。
2. 灵活复用:协议扩展+自定义协议
既然两个结构体都遵循CoreClass,而且有完全相同的属性,咱们可以封装一个通用协议来统一它们的行为:
// 先定义一个包含共同属性的协议 protocol PlaceProtocol { var id: String { get } var name: String { get } } // 让自动生成的结构体自动遵循这个协议(因为它们本来就有这些属性,不需要额外写实现) extension FromPlace: PlaceProtocol {} extension ToPlace: PlaceProtocol {}
之后你就可以用PlaceProtocol作为参数类型、返回值类型,来统一处理这两个结构体:
func displayPlace(_ place: PlaceProtocol) { print("地点ID:\(place.id),名称:\(place.name)") } // 不管是FromPlace还是ToPlace实例,都能传入这个方法 let departure = FromPlace(id: "DEP001", name: "北京首都机场") let destination = ToPlace(id: "DES001", name: "上海浦东机场") displayPlace(departure) displayPlace(destination)
这种方式的好处是扩展性极强——哪怕后续生成更多类似的结构体(比如ViaPlace),只要它有id和name属性,只需要加一行extension ViaPlace: PlaceProtocol {}就能复用所有基于PlaceProtocol的逻辑。
3. 严格统一:类型擦除(Type Erasure)
如果需要把不同类型的实例转换成同一个具体类型(比如放在同一个数组里),可以用类型擦除来包装它们:
struct AnyPlace: PlaceProtocol { let id: String let name: String // 接收任何遵循PlaceProtocol的类型 init<T: PlaceProtocol>(_ place: T) { self.id = place.id self.name = place.name } }
使用的时候把FromPlace或ToPlace实例包装成AnyPlace:
let anyDeparture = AnyPlace(departure) let anyDestination = AnyPlace(destination) // 现在它们都是AnyPlace类型,可以放在同一个数组里了 let journeyPlaces: [AnyPlace] = [anyDeparture, anyDestination]
这种方式适合需要对外暴露统一类型,或者需要集合操作的场景。
小提醒
记得把这些自定义的协议、扩展、类型别名放在单独的手动维护文件里,别和自动生成的代码混在一起,避免下次更新生成代码时被覆盖掉。
内容的提问来源于stack exchange,提问作者Sti
相关产品推荐
相关产品推荐

