2014-11-23 152 views
1

我想實現一個協議,它本身繼承多個協議,都有一個委託成員。有沒有乾淨的方式來做到這一點,而不需要爲每個協議的委託使用不同的名稱?Swift實現多個協議與委託

protocol ProtocolOne { 
    var delegate: ProtocolOneDelegate? 
} 

protocol ProtocolTwo { 
    var delegate: ProtocolTwoDelegate? 
} 

protocol CombinedProtocol: ProtocolOne, ProtocolTwo { 

} 

protocol CombinedDelegate: ProtocolOneDelegate, ProtocolTwoDelegte { 

} 

class ProtocolImpl: CombinedProtocol { 
    // How can I implement delegate here? 
    // I've tried the following options without success: 
    var delegate: CombinedDelegate? 
    var delegate: protocol<ProtocolOneDelegate, ProtocolTwoDelegate>? 
} 
+0

委託是符合協議的對象。我想不出爲什麼它有一個代表。 – vikingosegundo 2014-11-23 03:17:33

+0

@vikingosegundo我可以看到你的觀點,即委託屬於實現而不是協議。目前我只是從協議中刪除委託屬性,並且只在實現中聲明協議。如果你想發佈這個作爲答案,我會很樂意接受它。 – robhasacamera 2014-11-23 18:33:12

回答

2

在你的代碼中,delegate只是一個普通的屬性。您可以擁有多個協議,聲明具有相同名稱和相同類型的屬性,並有一個類直接或間接實現它。

如果不同的協議定義了一個具有相同名稱但類型不同的屬性,那麼您將無法編譯它,因爲編譯器會抱怨重新聲明屬性和類沒有確認其中一個協議。

有2種可能的解決方案。最明顯的是避免使用在其他協議中使用的概率很高的名稱 - delegate是一個典型情況。使用不同的命名慣例,如protocol1DelegatedataSourceDelegateapiCallDelegate

的第二溶液由具有方法替換性質。例如:

protocol P1 { 
    func test() -> String? 
} 

protocol P2 { 
    func test() -> Int? 
} 

protocol P3: P1, P2 { 

} 

class Test : P3 { 
    func test() -> String? { return nil } 
    func test() -> Int? { return nil } 
} 

Swift認爲函數具有相同的參數列表,但返回類型與重載不同。但是請注意,如果2個協議使用相同的函數簽名(名稱,參數和返回類型),那麼在類中實現時,您將實現該函數一次 - 在某些情況下可能是想要的行爲,但在其他情況下可能不需要。

+0

我真的很想避免讓不同名稱的代表出現,我已經做到了這一點,並且效果不佳。另外,我並不知道你可能會重載Swift中的函數返回值。但是,我試圖超載的財產,並沒有奏效。這意味着即使外部方法名稱與內部相同,我仍然需要兩個名稱不同的屬性來跟蹤它們。 – robhasacamera 2014-11-23 18:29:28

2

解決方案可能是使用協議擴展(請檢查extension Combined)。好處是Combined只聲明delegateoneDelegatetwoDelegate是交叉實現計算。不幸的是,要求將三個變量暴露在課堂外,這可能是不方便的。

// MARK: - Delegates protocols 

protocol OneDelegate { 
    func oneDelegate(one: One) 
} 
protocol TwoDelegate { 
    func twoDelegate(two: Two) 
} 
protocol CombinedDelegate: OneDelegate, TwoDelegate { 
    func combinedDelegate(combined: Combined) 
} 


// MARK: - Model protocols 

protocol One: class { 
    var oneDelegate: OneDelegate? { get } 
} 

protocol Two: class { 
    var twoDelegate: TwoDelegate? { get } 
} 

protocol Combined: One, Two { 
    var delegate: CombinedDelegate? { get } 
} 

extension Combined { 
    var oneDelegate: OneDelegate? { 
     return delegate 
    } 
    var twoDelegate: TwoDelegate? { 
     return delegate 
    } 
} 


// MARK: - Implementations 

class Delegate: CombinedDelegate { 
    func oneDelegate(one: One) { 
     print("oneDelegate") 
    } 

    func twoDelegate(two: Two) { 
     print("twoDelegate") 
    } 

    func combinedDelegate(combined: Combined) { 
     print("combinedDelegate") 
    } 
} 

class CombinedImpl: Combined { 
    var delegate: CombinedDelegate? 

    func one() { 
     delegate?.oneDelegate(self) 
    } 

    func two() { 
     delegate?.twoDelegate(self) 
    } 

    func combined() { 
     delegate?.combinedDelegate(self) 
    } 
} 


// MARK: - Usage example 

let delegate = Delegate() 
let protocolImpl = CombinedImpl() 
protocolImpl.delegate = delegate 
protocolImpl.one() 
protocolImpl.two() 
protocolImpl.combined() 
2

您應該能夠將它們結合在一個:

var delegate: (ProtocolOneDelegate & ProtocolTwoDelegate)? 

您現在可以使用這兩種協議。