GetListItem类不遵循EveryUserDocument协议的原因及解决方法咨询
报错原因及解决办法
报错原因
1. 数组类型不匹配
协议EveryUserDocument明确要求relations的类型为[EveryUserDocumentRelation],但GetListItem中定义的relations是[GetListItemRelation]。尽管GetListItemRelation遵守了EveryUserDocumentRelation协议,但Swift中具体类型数组与协议类型数组属于不同类型,无法直接满足协议的精确类型要求。
2. 未完全实现Equatable协议
EveryUserDocument继承了Equatable协议,而GetListItem是继承自NSObject的类:
- NSObject默认的
==运算符是基于对象引用的相等判断,不符合自定义类基于属性的相等需求; - Swift不会为继承自NSObject的类自动合成
Equatable的实现,必须手动提供==运算符的自定义实现,否则编译器会判定未遵守协议。
解决办法
方法一:调整数组类型为协议类型并实现Equatable
将GetListItem的relations类型改为协议类型数组,同时手动实现Equatable协议:
public class GetListItem: NSObject, Codable, EveryUserDocument { public let id: Int public let relations: [EveryUserDocumentRelation] // 修改为协议类型数组 enum CodingKeys: String, CodingKey { case id case relations } // 自定义Equatable实现 public static func == (lhs: GetListItem, rhs: GetListItem) -> Bool { lhs.id == rhs.id && lhs.relations.elementsEqual(rhs.relations) { $0.id == $1.id && $0.objectClass == $1.objectClass } } } public class GetListItemRelation: NSObject, Codable, EveryUserDocumentRelation { public let id: Int public let objectClass: String enum CodingKeys: String, CodingKey { case id case objectClass } } protocol EveryUserDocument: Equatable { var id: Int { get } var relations: [EveryUserDocumentRelation] { get } } protocol EveryUserDocumentRelation { var id: Int { get } var objectClass: String { get } }
如果希望关系类型也支持相等判断,可以让EveryUserDocumentRelation继承Equatable,并在GetListItemRelation中实现==:
protocol EveryUserDocumentRelation: Equatable { var id: Int { get } var objectClass: String { get } } public class GetListItemRelation: NSObject, Codable, EveryUserDocumentRelation { public let id: Int public let objectClass: String enum CodingKeys: String, CodingKey { case id case objectClass } public static func == (lhs: GetListItemRelation, rhs: GetListItemRelation) -> Bool { lhs.id == rhs.id && lhs.objectClass == rhs.objectClass } }
此时GetListItem的==可以简化为:
public static func == (lhs: GetListItem, rhs: GetListItem) -> Bool { lhs.id == rhs.id && lhs.relations.elementsEqual(rhs.relations) }
方法二:使用关联类型实现灵活的类型匹配
修改EveryUserDocument协议,通过关联类型允许使用符合协议的具体类型数组:
protocol EveryUserDocument: Equatable { associatedtype RelationType: EveryUserDocumentRelation var id: Int { get } var relations: [RelationType] { get } } public class GetListItem: NSObject, Codable, EveryUserDocument { public let id: Int public let relations: [GetListItemRelation] enum CodingKeys: String, CodingKey { case id case relations } public static func == (lhs: GetListItem, rhs: GetListItem) -> Bool { lhs.id == rhs.id && lhs.relations == rhs.relations } } public class GetListItemRelation: NSObject, Codable, EveryUserDocumentRelation, Equatable { public let id: Int public let objectClass: String enum CodingKeys: String, CodingKey { case id case objectClass } public static func == (lhs: GetListItemRelation, rhs: GetListItemRelation) -> Bool { lhs.id == rhs.id && lhs.objectClass == rhs.objectClass } } protocol EveryUserDocumentRelation { var id: Int { get } var objectClass: String { get } }
这种方式保留了具体类型数组的类型安全,同时满足协议要求,适用于需要针对不同文档类型使用不同关系类型的场景。
内容的提问来源于stack exchange,提问作者Lavrin Pristazh
相关产品推荐
相关产品推荐

