CBUUID已遵循DCUUID,为何CBAttribute仍无法遵循DCPipe协议?
问题描述
定义了如下协议:
public protocol DCUUID { init(string: String) var uuidString: String { get } } public protocol DCPipe { var uuid: DCUUID { get } }
尝试让系统类遵循协议:
extension CBUUID: DCUUID {} extension CBAttribute: DCPipe {}
但编译器提示CBAttribute未遵循DCPipe协议,尽管CBAttribute本身拥有属性:
var uuid: CBUUID { get }
且CBUUID已遵循DCUUID协议。
问题原因
Swift的协议一致性检查要求属性类型完全匹配,协变关系在这里不生效。DCPipe协议要求uuid属性的类型是DCUUID(协议类型),而CBAttribute原生的uuid属性类型是具体的CBUUID——虽然CBUUID遵循DCUUID,但这两个类型并不等价,编译器不会自动将具体类型的属性视为满足协议中抽象类型的要求。
解决方案
有两种常用的解决方式:
方式一:为
DCPipe协议添加关联类型
修改DCPipe协议,通过关联类型约束uuid的类型必须遵循DCUUID,编译器会自动推断CBAttribute的uuid属性符合要求:public protocol DCPipe { associatedtype UUIDType: DCUUID var uuid: UUIDType { get } } // 无需额外实现即可通过编译 extension CBAttribute: DCPipe {}方式二:在
CBAttribute的扩展中显式实现协议要求
如果不想修改DCPipe协议,可以在扩展中显式声明符合协议类型的uuid属性,将原生的CBUUID实例向上转换为DCUUID类型:extension CBAttribute: DCPipe { public var uuid: DCUUID { return self.uuid as DCUUID } }注:此处属性名与原生
uuid重名,但由于类型不同,编译器会将其视为协议要求的实现,不会产生冲突。
内容的提问来源于stack exchange,提问作者Alexey
相关产品推荐
相关产品推荐

