2017-08-28 32 views
0

我實現如下組成結構:錯誤多約束擴展實現調用

protocol ProtocolA { 
    func doStuff() 
} 

protocol ProtocolB { } 

extension ProtocolA { 
    func doStuff() { 
    print("From protocol A") 
    } 
} 

extension ProtocolA where Self: ProtocolB { 
    func doStuff() { 
    print("From protocol B") 
    } 
} 

和我有以下類:

class MyClassA: ProtocolA { 
    func letsDoSomething() { 
     self.doStuff() 
    } 
} 

class MyClassB: MyClassA, ProtocolB { 
} 

發生什麼事是:

let ia = MyClassA() 
ia.letsDoSomething() // From protocol A (OK!) 

let ib = MyClassB() 
ib.letsDoSomething() // From protocol A (Wrong!) 

當然,我不期望得到第二個答案。

Swift Programming Launguage導向指定:

如果貼合型滿足用於提供用於相同的方法或屬性實現多約束擴展的要求,SWIFT將使用對應於最專門約束的實施。

這是爲什麼符合ProtocolBib不會調用最專業的擴展實現?

我知道調用的類仍然是MyClassA但由於實例是從MyClassB是符合協議ProtocolB我仍然希望有最專業的執行被調用。

+0

比較https://stackoverflow.com/a/42286148/2976878和https://stackoverflow.com/a/44706021/2976878點#2。 'MyClassB'不符合'ProtocolA';它依賴於'MyClassA'的一致性。 – Hamish

+0

我同意,這就是爲什麼我希望有儘可能結果'\\從協議B'。你不同意嗎? –

+1

否; 'MyClassB'依賴於'MyClassA'與'ProtocolA'的一致性。 'MyClassA'不符合'ProtocolB',所以受約束的擴展方法不能滿足它的一致性。因此,無約束擴展方法滿足其一致性,因此就是所謂的。 – Hamish

回答

1

問題是MYClassB從MyClass的A.斯威夫特的方法調度規則繼承了這個孩子類的實現,不會被調用默認的實現總是以協議一致性的情況下使用。嘗試同樣的情況下,這樣的

class MyClassA: ProtocolA { 
    func letsDoSomething() { 
     self.doStuff() 
    } 
} 

class MyClassB: ProtocolA, ProtocolB { 
} 


let ia = MyClassA() 
ia.letsDoSomething() // From protocol A (OK!) 

let ib = MyClassB() 
ib.doStuff() // From protocol A (Wrong!) 
+0

問題是究竟使用在'MyClassA'已經實施letsFoSomething'的'執行,而且更換doStuff的'的行爲()'使用約束執行'擴展ProtocolA的地方自我:ProtocolB'。 按照你的解決方案,我需要複製粘貼包含在'lestDoSomething'共享代碼。 我不知道我正確解釋的地步。清楚嗎?你有什麼想法如何能不復制粘貼來實現'ia.letsDoSomething()'執行? –