Swift中的Override协议扩展默认实现

您可能需要阅读https://team.goodeggs.com/overriding-swift-protocol-extension-default-implementations-d005a4428bda

这是我在Medium写作中缺席了很长时间(可能是四个月)之后的下一个故事,所以请耐心等待您。

我读过人们在使自己的Swift代码更紧凑并遵循面向协议的编程方面遇到问题。 两者都可以实现,但也有一些局限性。

让我告诉你我的情况。

在上面的代码中,我有一个协议X ,我想让UIView实现它。 然后,要实现XUIView必须提供方法x() ,我们知道。

但是,假设我们要override UIStackViewx()实现,它是UIView子类。 问题来了。 扩展不能被覆盖,因为Swift实现扩展的方式是使用静态分派,这意味着在编译时就可以解决。

阅读https://www.raizlabs.com/dev/2016/12/swift-method-dispatch/

好的,如果您的目标是编译代码,那么上面的代码实际上可以使用一些技巧进行编译。

首先,由于编译器声明我们不能覆盖扩展中的non-objc声明,因此我们必须使要实现的方法成为@objc方法。 该解决方法使该方法成为动态调度。 在运行时解决!

可是等等! 它运行正常吗?

啊,它在运行时有效!

我们快乐,可以实现子类中最重要的扩展! 但是有局限性。

使用@objc意味着您的协议要求签名应与@objc兼容。 如果您根据与@objc不兼容的类型提出了要求,该怎么@objc ? 当然,您不能做太多事。 局限性令人恐惧!

让我们看看另一种方法。

自我约束协议扩展

使用此方法,您不需要向@objc公开任何内容,因为此解决方法是完全Swift的。 但是,让我给您一个线索,这不适用于动态调度。 这样可以编译,但是如果您调用隐藏在其超类类型下的方法,则代码将存在错误。

是的,它可以正确编译。 但是它在运行时有效吗?

如您在Debug输出中所见。 当我们在隐藏在UIView下的UIStackView中调用x()时,就好像我们@objc上面使用@objc 。 那是因为s在编译时解析为使用where Self: UIView实现来调用x()

结论

如果您的实现应该动态地分派,则不得使用此override来与协议扩展一起使用。 您总是有机会使用@objc及其局限性,或者可以使用constrained protocol extension ,而@objc担心隐藏在客户端代码中的错误。 明智的朋友。

PS:我已经在此库ViewDSL中实现了@objc版本