协议扩展中的 Swift 属性观察器?

Posted

技术标签:

【中文标题】协议扩展中的 Swift 属性观察器?【英文标题】:Swift property observer in protocol extension? 【发布时间】:2015-11-23 03:48:32 【问题描述】:

考虑以下几点:

protocol ViewControllable: class 
  typealias VM: ViewModellable
  var vm: VM!  get 
  func bind()


extension ViewControllable 
  var vm: VM! 
    didSet 
      bind()
    
  

我正在尝试观察vm 属性并在注入时调用bind。但这不会编译错误:

扩展可能不包含存储的属性

这是有道理的,因为协议不能强制属性为storedcomputed

不引入class inheritance是否可以做到这一点?

换句话说,我可以观察协议扩展内的属性变化吗?

【问题讨论】:

请注意,您确实可以很容易地做到这一点,如果您使用关联的属性。这是我最近发表的关于如何创建关联属性的帖子:example 在撰写本文时这很新鲜,所以希望它相当稳定。 关于这个问题,一个完美的例子,你可以在哪里使用这个是这个QA中使用的例子:***.com/questions/41910120/… @Fattie 你能修复那个链接吗?我目前无法查看您的帖子或示例。 啊,你的意思是第一个链接!请注意,SO 关闭了“文档”功能。不幸的是,这个例子永远消失了。对不起! 在这里,我想:web.archive.org/web/20170221052848/http://***.com/… 【参考方案1】:

不,这是明确禁止的。见Extension: Computed Properties:

扩展可以添加新的计算属性,但它们不能添加存储的属性,或者向现有属性添加属性观察器。

请记住,如果这是合法的,则会在执行顺序方面增加一些不小的混乱。想象一下有几个扩展添加了didSet,而实际实现也有一个didSet。他们应该按什么顺序运行?这并不意味着它不可能实现,但如果我们拥有它可能会有些令人惊讶。

【讨论】:

感谢您的澄清。但我不同意它可能带来的混乱。许多其他编程语言通过使它们显式编译错误或从声明的顺序推断来处理这种菱形问题。例如,Scala 在发生冲突时,优先考虑在类 extends (:) 之后声明的 trait (protocol)。 > "他们应该按什么顺序运行?"真的吗?我自然想拥有这个功能。例如。你有一个新客户。您唯一关心的信息是他的唯一标识符。您设置标识符。设置此标识符后,协议方法会获取我们需要的有关客户的所有信息。以正确的顺序执行代码并不难我希望代码负责其余的工作,而不必关心手动调用所有函数。就像现在一样,在没有这个的情况下使用协议和扩展会让人感觉不舒服 uuuh 心痛:( @Ferologics 和其他人 - 如果您愿意使用相关属性,您确实可以这样做。请参阅我在问题下的评论。

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

Swift 使协议扩展成为通知观察者

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

Swift 中带有选择器的协议扩展

swift3.0 扩展协议

Swift 扩展(Extension)总结

Swift - 协议扩展 - 属性默认值