为什么Swift中协议类型实例调用属性优先触发扩展默认实现
核心原因
你定义的TestClass并没有合规实现SampleProtocol的属性要求,所以编译器会默认采用协议扩展的默认实现来满足协议约束:
- 协议中要求
sample属性是可读写属性(声明为{get set}) - 你在
TestClass中实现的sample是只读属性,仅提供了get逻辑没有实现set,这个实现并不匹配协议的约定,不属于对协议要求的合规实现。
两种调用结果不同的调度逻辑
- 直接调用
testObj.sample时,testObj是具体的TestClass类型,编译器做静态调度,会优先调用TestClass中定义的只读sample属性,因此输出"TestClass"。 - 实例传入
printValue方法时,参数被类型擦除为SampleProtocol协议类型,编译器会按照协议约定派发调用:由于TestClass没有合规实现协议要求的可读写sample,因此直接调用协议扩展的默认实现,输出nil。
验证方案
你可以修改TestClass的实现,补充set逻辑满足协议的可读写要求:
class TestClass:SampleProtocol { var sample: String?{ get { return "TestClass" } set {} // 补充set实现,匹配协议的{get set}要求 } }
修改后两次打印都会输出"TestClass"。
内容的提问来源于stack exchange,提问作者Jai Deves
相关产品推荐
相关产品推荐

