了解协议扩展中的 Swift 默认值属性

Posted

技术标签:

【中文标题】了解协议扩展中的 Swift 默认值属性【英文标题】:Understanding Swift default valued properties inside a Protocol extension 【发布时间】:2022-01-02 15:18:54 【问题描述】:

我有这个示例协议,它有一个带扩展名的默认值属性。

protocol SampleProtocol
    var sample:String?get set

extension SampleProtocol
    var sample:String? get  return nil  set 

现在,我的 TestClass 实现了 SampleProtocol,如下所示。

class TestClass:SampleProtocol 
    var sample: String?
        return "TestClass"
    

还有一种辅助方法可以打印来自 SampleProtocol 的样本值。

func printValue(_ value: SampleProtocol)
    print(value.sample)

现在问题来了

let testObj = TestClass()
print(testObj.sample) // prints "TestClass"
printValue(testObj) // prints nil

从上面的结果,我需要明白为什么当testObj被类型转换为SampleProtcol时,它考虑的是扩展的默认实现而不是TestClass的实现?

【问题讨论】:

您正在 TestClass 中创建一个新的计算 var,而不是使用协议 var.. 在 TestClass 中尝试这个 var sample: String? = "TestClass" 我不知道其根本原因,但它不起作用,因为您的类中有一个计算属性,如果您将其更改为存储属性,您将获得预期的行为跨度> 哇,将sample 更改为存储属性效果很好。我的意思是,如果你们知道的话,任何解释或 Swift 文档都会非常有帮助。 【参考方案1】:

问题是TestClass 没有实现SampleProtocol,所以当你在接受SampleProtocolprintValue 方法中传递它时,它将调用协议扩展中的默认实现(因为实例你传递的没有实现协议方法)。

SampleProtocol 中您已将变量定义为 get set 但在TestClass 变量中您只提供了一个 getter,这不符合要求(如果您删除协议扩展,您将看到一个错误该类不符合协议)。

如果你提供一个 setter 就可以了:

class TestClass: SampleProtocol 
    var sample: String? 
        get 
        return "TestClass"
         set  
    

【讨论】:

以上是关于了解协议扩展中的 Swift 默认值属性的主要内容,如果未能解决你的问题,请参考以下文章

使用 Swift 4 中的 JSONDecoder,缺少的键可以使用默认值而不是可选属性吗?

使用 Swift 4 中的 JSONDecoder,缺少的键可以使用默认值而不是可选属性吗?

使用 Swift 4 中的 JSONDecoder,缺少的键可以使用默认值而不是可选属性吗?

Swift如何兼顾协议中默认和自定义方法的调用?

协议中的默认初始化程序需要不需要的可变属性

6.Swift协议|扩展|访问权限|异常调试|类型转换|运算函数|ARC|类类型初试化器|值类型初始化器