【iOS-Swift】为什么是面向协议的编程 struct+protocol

本文介绍了Swift协议的特性,包括作为类型约束、抽象接口和无痕扩展。强调了协议在结构体和枚举中的应用,以及与Objective-C协议的区别。通过一个Demo展示了如何为UIView无痕扩展方法,阐述了协议如何促进代码共享并避免了面向对象中的继承限制。此外,还探讨了动态派发的复杂性和关联类型的影响。
摘要由CSDN通过智能技术生成
  • swift 基本类都是继承于协议
  • swift 可以通过协议的默认实现,进行无痕扩展
Swift 的协议和 Objective-C 的协议不同。Swift 协议可以被用作代理,也可以让你对接口进行
抽象 (比如 IteratorProtocol 和 Sequence)。它们和 Objective-C 协议的最大不同在于我们可以
让结构体和枚举类型满足协议。除此之外,Swift 协议还可以有关联类型。我们还可以通过协议
扩展的方式为协议添加方法实现。我们会在面向协议编程的部分讨论所有这些内容。
协议允许我们进行动态派发,也就是说,在运行时程序会根据消息接收者的类型去选择正确的
方法实现。不过,方法到底什么时候是动态派发,什么时候不是动态派发,有时却不是那么直
观,并有可能造成令人意外的结果。我们会在下一节中看到这个问题。
普通的协议可以被当作类型约束使用,也可以当作独立的类型使用。带有关联类型或者 Self 约
束的协议特殊一些:我们不能将它当作独立的类型来使用,所以像是 let x: Equatable 这样的
写法是不被允许的;它们只能用作类型约束,比如 func f<T: Equatable>(x: T)。这听起来似乎
是一个小限制,但是这在实践中让带有关联类型的协议成为了完全不同的东西。我们会在之后
详细对此说明,我们还将讨论如何使用 (像是 AnyIterator 这样的) 类型消除的方法来让带有关
联类型的协议更加易用。
在面向对象编程中,子类是在多个类之间共享代码的有效方式。一个子类将从它的父类继承所
有的方法,然后选择重写其中的某些方法。比如,我们可以有一个 AbstractSequence 类,以
及像是 Array 和 Dictionary 这样的子类。这么做的话,我们就可以在 AbstractSequence 中添
加方法,所有的子类都将自动继承到这些方法。
不过在 Swift 中,Sequence 中的代码共享是通过协议和协议扩展来实现的。通过这么做,
Sequence 协议和它的扩展在结构体和枚举这样的值类型中依然可用,而这些值类型是不支持
子类继承的。
不再依赖于子类让类型系统更加灵活。在 Swift (以及其他大多数面向对象的语言) 中,一个类
只能有一个父类。当我们创建一个类时,我们必须同时选择父类,而且我们只能选择一个父类,
我们无法创建比如同时继承了 AbstractSequence 和 Stream 的类。这有时候会成为问题。在
Cocoa 中就有一些例子,比如 NSMutableAttributedString,框架的设计师必须在
NSAttributedString 和 NSMutableString 之间选择一个父类。

Demo 给UIView 无痕扩展一个方法

// 给 UIView 扩展一个方法 test()
// 扩展方式优美有和谐
struct TestFunction<TE> {
    let base: TE
    init(_ te: TE) {
        base = te
    }
}

protocol TestFunctionProtocol {
    associatedtype Compatible
    var tb: TestFunction<Compatible> { get }
    static var tb : TestFunction<Compatible>.Type { get }
}

extension TestFunctionProtocol {
    var tb: TestFunction<Self> {
        return TestFunction(self)
    }
    static var tb : TestFunction<Self>.Type {
        return TestFunction<Self>.self
    }
}
// 下面注释代码保证 TestFunction 不会重复创建
//var tbbb = "tb"
//extension TestFunctionProtocol {
//    var tb: TestFunction<Self> {
//        var cache = objc_getAssociatedObject(self, &tbbb)
//        if let cache = cache {
//            return cache as! TestFunction<Self>
//        }
//        cache = TestFunction(self)
//        objc_setAssociatedObject(self, &tbbb, cache, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
//        return cache as! TestFunction<Self>
//    }
//    static var tb : TestFunction<Self>.Type {
//        return TestFunction<Self>.self
//    }
//}


extension TestFunction where TE: UIView {
    func test() {
        print("this is my test")
    }
}

extension UIView: TestFunctionProtocol {}

let v = UIView()
v.tb.test()

您的一举一动都是对我的莫大支持

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值