Swift学习之协议三

作者: 冷武橘 | 来源:发表于2020-09-22 14:10 被阅读0次

    面向协议编程 (Protocol Oriented Programming,以下简称 POP) 是 Apple 在 2015 年 WWDC 上提出的 Swift 的一种编程范式。相比与传统的面向对象编程 (OOP),POP 显得更加灵活。

    • 如何将BVC和DVC的公共方法 testMethod抽取出来
    class BVC: UIViewController
    {
        func testMethod() {
            print("测试方法")
        }
    }
    
    class DVC:UITableViewController{
        func testMethod() {
            print("测试方法")
        }
    }
    

    一、OOP解决方案

    1、用新的类型来提供这个功能
    class testTool{
        func testMethod() {
            print("测试方法")
        }
        
    }
    
    class ViewCotroller: UIViewController
    {
        var testtool:testTool?
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            self.testtool = testTool()
            self.testtool?.testMethod()
        }
    }
    
    
    class tableViewContoller:UITableViewController{
        var testtool:testTool?
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
         self.testtool = testTool()
         self.testtool?.testMethod()
        }
    }
    
    • 依赖注入引入额外的依赖关系,可能也是我们不太愿意看到的。
    2、UIViewController 上添加 extension
    extension UIViewController{
        func testMethod() {
            print("测试方法")
        }
    }
    let v = ViewCotroller()
    v.testMethod()
    
    let t = tableViewContoller()
    t.testMethod()
    
    • 看起来这是一个稍微靠谱的做法,但是给任何UIViewController类都添加了testMethod,这种添加代码影响也是不可估计 的,不想看到的。

    二、POP解决方案

    import UIKit
    
    protocol test{
    
       func testMethod()
    }
    
    
    extension test{
    
        func testMethod(){
            print("测试方法")
        }
        
    }
    
    
    class ViewCotroller: UIViewController,test
    {
      
    }
    
    
    class tableViewContoller:UITableViewController,test{
    
    }
    
    let  v = ViewCotroller()
    
    let  t = tableViewContoller()
    
    v.testMethod()
    t.testMethod()
    
    • 通过易个协议扩展,我们只需要简单地声明 ViewController 和 tableViewContoller 遵守 test,就可以直接使用 testMethod 的实现了:

    三、POP的应用

    使用注意点:

    • 1、 优先考虑创建协议,而不是父类(基类)
    • 2、优先考虑值类型(struct、enum),而不是引用类型(class)
    • 3、巧用协议的扩展功能
    • 4、不要为了面向协议而使用协议。

    四、优雅的前缀

    如果我们设计一个可以计算字符串长度的方法

    4.1、直接扩展一个方法

    extension String{
        func numberCount() -> Int {
            return self.count
        }
    }
    print(string.numberCount())
    

    4.2、扩展一个计算属性

    extension String{
        var mj_numberCount :Int{
            return self.count
        }
    }
    print(string.mj_numberCount)
    

    4.3、加一个前缀避免和系统方法冲突

    struct Mj {
        var string:String
        init(_ str:String) {
            self.string = str
        }
        var numberCount :Int{
            return self.string.count
        }
    }
    extension String{
        var mj:Mj{return Mj(self)}
    }
    print(string.mj.numberCount)
    
    struct Mj<Base>{
        var base:Base
        
        init(_ base:Base) {
            self.base = base;
        }
       
    }
    extension String{
        var mj:Mj<Self>{return Mj(self)}
    }
    
    extension Int{
        var mj:Mj<Self>{return Mj(self)}
    }
    
    
    extension Mj where Base == String{
        var numbercount :Int{
            return self.base.count
        }
    }
    
    extension Mj where Base == Int{
        var  floatcount :Float{
            return Float(self.base)
        }
    }
    
    
    var string = "测试"
    print(string.mj.numbercount)
    
    var a = 10
    print(a.mj.floatcount)
    

    4.4、使用协议优雅的添加一个前缀

    
    
    struct Mj<Base>{
        var base:Base
        
        init(_ base:Base) {
            self.base = base;
        }
       
    }
    
    protocol MJCompatable{}
    
    
    extension MJCompatable{
        var mj:Mj<Self>{
            get {Mj(self)}
            set{}
        }
    }
    
    
    extension String:MJCompatable{}
    
    
    extension Mj where Base == String{
        var numbercount :Int{
            return self.base.count
        }
    }
    
    
    extension Int:MJCompatable{}
    
    extension Mj where Base == Int{
        var  floatcount :Float{
            return Float(self.base)
        }
    }
    
    
    var string = "测试"
    print(string.mj.numbercount)
    
    var a = 10
    print(a.mj.floatcount)
    

    五、使用协议实现类型判断

    判断一个是否为一个数组

    func isArray(_ value: Any)  -> Bool {
        value is [Any]
    }
    print(isArray(NSArray()))
    print(isArray([1,"2"]))
    print(isArray("123444"))
    
    import Foundation
    protocol Arraytype {}
    extension Array: Arraytype{}
    extension NSArray: Arraytype{}
    func isArrayType(_ type: Any.Type) -> Bool {
        type is Arraytype.Type
    }
    print(isArrayType([Int].self))
    print(isArrayType([Any].self))
    print(isArrayType(NSArray.self))
    isArrayType(NSMutableArray.self)
    

    相关文章

      网友评论

        本文标题:Swift学习之协议三

        本文链接:https://www.haomeiwen.com/subject/spwnyktx.html