天天看點

面向協定程式設計面向協定程式設計

面向協定程式設計

在使用 Swift 時,可以為結構體和枚舉類型聲明方法,其使用起來更加友善,對于一些簡單模型,或者對象的組合模型,使用結構體更為簡便。

對于面向對象程式設計(OOP,Object Oriented Programming)而言,類能夠更好的描述模型,并且可以将抽象出的通用屬定義在父類中。

但是,不管是 Objective-C 還是 Swift 語言,都不支援多繼承,但是他們都可以遵循多個協定。實際程式設計時,可以将不同的特性分類,定義在不同的協定中,然後通過遵循協定的方式來實作一類特性。

在 Objective-C 中,值類型既不繼承其他類型,也不能實作協定。如果要更多的使用值類型,那麼抽象出通用的屬性給不同值類型繼承,就十分必要。而 Swift 做得更多,所有的類型都可以遵循多個協定,而且協定本身可以實作預設的方法,如此,針對一類操作定義一個協定,那麼隻要遵循該協定,就可以獲得相應操作。

如同一個孩子的發質繼承自父親,而眼睛更像母親,那麼如果使用面向對象的方式進行描述,無法支援多繼承的情況下,隻能備援的将特性既聲明在父類中又聲明在子類中。而如果将特性聲明在協定中,父類和子類遵循相同的協定就表示擁有同一個特質,而子類再遵循一個描述母親眼睛特性的協定即可。

是以,面向協定程式設計(POP,Protocol Oriented Programming)是通過不同協定的繼承群組合來描述事物。可以說,面向對象更多的是對一類事物通用特性的抽象,而面向協定更多的是對不同僚物通用特性的抽象。前者更注重整體特性的抽象,後者是對特性更細粒度的抽象。通過不同特性的組合來描述一類事物,比通過層層繼承來描述一類事物更加簡化,更加具體,代碼備援度也會下降。

例如,在應用架構的設計時,也可以使用面向協定程式設計的思想,我們可以将以前寫入基類中的一些屬性或方法,定義在協定中,通過遵循協定來使相應的類型獲得需要的屬性或方法。

protocol HXJRootProtocol: NSObject {
    
    var isSafeContentViewEnable: Bool { get set }
    
    var safeContentView: UIView! { get }
}

extension UIViewController: HXJRootProtocol {
    
    private static let safeContentViewTag: Int = 1000
    
    var safeContentView: UIView! {
        assert(isSafeContentViewEnable, "需要先設定 isSafeContentViewEnable 為 true 才可以使用 safeContentView")
        if let view = view.viewWithTag(UIViewController.safeContentViewTag) {
            return view
        }
        return nil
    }
    
    
    var isSafeContentViewEnable: Bool {
        set {
            if newValue {
                if nil != view.viewWithTag(UIViewController.safeContentViewTag) { return }
                addSafeContentView()
            }else {
                if let view = view.viewWithTag(UIViewController.safeContentViewTag) {
                    view.removeFromSuperview()
                }
            }
        }
        
        get {
            return view.viewWithTag(UIViewController.safeContentViewTag) != nil
        }
    }
    
    private func addSafeContentView() {
        
        let safeContentView = UIView.init()
        view.addSubview(safeContentView)
        
        safeContentView.backgroundColor = .clear
        safeContentView.tag = UIViewController.safeContentViewTag
        safeContentView.translatesAutoresizingMaskIntoConstraints = false
        
        safeContentView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
        safeContentView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
        
        if #available(iOS 11.0, *) {
            safeContentView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true
            safeContentView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor).isActive = true
        } else {
            safeContentView.topAnchor.constraint(equalTo: self.topLayoutGuide.bottomAnchor).isActive = true
            safeContentView.bottomAnchor.constraint(equalTo: self.bottomLayoutGuide.topAnchor).isActive = true
        }
    }
        
}
           

在上面的代碼中,通過使 UIViewController 遵循 HXJRootProtocol 協定,來添加一個安全區域的視圖。

雖然無法為一個類型擴充存儲屬性,但是如果有必要,可以使用運作時的方法來實作該需求。