2016-07-26 59 views
2

我想重寫協議擴展的實例方法,並且遇到了一些麻煩。如何在Swift中重寫協議擴展的實例方法?

對於上下文,我正在製作一個帶有許多不同UICollectionViews的iOS應用程序。這些視圖從不同的數據庫獲取數據(需要不同的回調函數)並且佈局非常不同。因爲(數據庫,佈局)的任何組合都是可能的,所以很難在沒有大量代碼重複的情況下創建一個不錯的OOP類層次結構。

我的想法是將佈局函數(主要是UICollectionViewDelegateFlowLayout協議中定義的那些函數)放入協議擴展中,這樣我就可以用一個擴展來實現所有相關佈局函數的協議來修飾給定的UICollectionView子類,但是我這很困難。問題的實質包含在下面的代碼中。

class Base { 
    func speak(){ 
     print("Base") 
    } 
} 

class SubA: Base, ProtocolA {} 

class SubB: Base, MyProtocolB {} 

protocol MyProtocolA{ 
    func speak() 
} 

protocol MyProtocolB{ 
    func speak() 
} 

extension MyProtocolA{ 
    func speak(){ 
     print("A")   
    } 
} 

extension MyProtocolA{ 
    func speak(){ 
     print("B")   
    } 
} 

let suba = SubA() 
suba.speak() // prints "Base", I want it to print "A" 

let subb = SubB() 
subb.speak() // prints "Base", I want it to print "B" 

想法?

+2

「我的想法是將佈局函數(主要是在UICollectionViewDelegateFlowLayout協議中定義的函數)放入協議擴展中」忘記了這個想法。 Objective-C永遠不會從協議擴展中調用實現,因爲Objective-C不能查看協議擴展。它是一個Swift專用功能。 – matt

+0

@matt這個問題不是關於Obj-C,不是嗎? –

+2

@TimVermeulen是的。它是關於Swift協議擴展中的Objective-C委託方法。 – matt

回答

2

只有符合這些協議的類不自己實現該方法時,纔會調用協議中的默認實現。類的方法覆蓋協議的默認實現,而不是相反。

通常情況下,你會做這樣的事情:

protocol MyProtocolA { 
    func speak() 
} 

protocol MyProtocolB { 
    func speak() 
} 

extension MyProtocolA { 
    func speak() { 
     print("A")   
    } 
} 

extension MyProtocolB { 
    func speak() { 
     print("B")   
    } 
} 

class SubA: MyProtocolA {} 

class SubB: MyProtocolB {} 

let suba = SubA() 
suba.speak() // prints "A" 

let subb = SubB() 
subb.speak() // prints "B" 

但是,如果你

class SubC: MyProtocolA { 
    func speak(){ 
     print("C") 
    } 
} 

let subc = SubC() 
subc.speak() // prints "C" 

坦率地說,你看看這個,使用Base在這個例子中完全多餘的,所以我刪除了它。顯然,如果您需要從Base中繼承其他原因,請隨意。但關鍵是協議默認實現不會覆蓋類的實現,而是相反。

+0

很好的答案,謝謝Rob。後續工作:如何在沒有代碼重用的情況下實施? 「this」是指像我們這裏(任何子類都需要基於數據庫和佈局實現功能)的任何2變量混合匹配場景。該功能不適用於層次結構。 –

+0

我沒跟着你。你能舉一個你的意思的實際例子嗎? – Rob

+0

所以我的應用程序有UICollectionViews a)有不同的佈局和b)從不同的數據庫中獲取他們的數據。更具體地說,我有一個「圖標」佈局和「細節」佈局,其中每個佈局覆蓋cellForItemAtIndexPath和許多UICollectionViewDelegateFlowLayout方法。不過,我也有兩個數據庫,根據CollectionView從哪個數據庫抓取數據,需要不同的代碼。所以{數據庫1,數據庫2} x {圖標,細節}的任何組合都需要它自己的子類。但是如果沒有代碼重複,你無法真正做到這一點 –