Swift中如何让类遵循带子类约束的Restorable协议?
解决方案:利用关联类型让协议支持具体子模型类型
当然有办法解决这个问题!核心思路是利用Swift的**关联类型(associatedtype)**来让Restorable协议支持具体的子模型类型,这样既满足协议约束,又能让你的UIView子类使用更具体的模型类型,简化初始化流程。
问题根源
原来的Restorable协议要求storyItem的类型是StoryItem?,虽然TextItem遵循StoryItem,但Swift中协议的属性实现要求类型完全匹配(协议的属性类型是不变的,不支持协变),所以直接用TextItem?实现会触发编译错误。
改造步骤
修改
Restorable协议,添加关联类型
给协议添加一个关联类型,并约束它遵循StoryItem,这样每个遵循协议的类型可以指定自己的具体模型类型:// 父协议(改造后) public protocol Restorable: AnyObject { associatedtype ItemType: StoryItem var storyItem: ItemType? { get set } }更新UIView子类的实现
现在你的ResizableLabel可以直接用TextItem?作为storyItem的类型,编译器会自动推断ItemType为TextItem,满足协议约束:class ResizableLabel: UILabel, Restorable { var storyItem: TextItem? }
完整代码示例
// 超模型协议 public protocol StoryItem { var id: Int64? { get } } // 父协议(改造后) public protocol Restorable: AnyObject { associatedtype ItemType: StoryItem var storyItem: ItemType? { get set } } // 具体模型结构体 public struct TextItem: StoryItem { public var id: Int64? public var text: String? } // 可正常编译的类 class ResizableLabel: UILabel, Restorable { var storyItem: TextItem? }
额外说明
- 这个方案让你在初始化
ResizableLabel时可以直接传入TextItem实例,无需类型转换,大大简化了初始化流程。 - 如果需要处理多个不同
Restorable类型的集合(比如[Restorable]),由于关联类型的存在,直接使用会触发编译错误,此时你需要实现类型擦除(比如创建一个AnyRestorable类型),但如果只是单个类或泛型场景下使用,上面的方案已经完全够用。
内容的提问来源于stack exchange,提问作者Roi Mulia
相关产品推荐
相关产品推荐

