我正在尝试实现一个本身继承多个协议的协议,这些协议都有一个委托成员。是否有一种干净的方法来执行此操作而不需要为每个协议的委托使用不同的名称?
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 :(得分:11)
您应该能够将它们组合在一起:
var delegate: (ProtocolOneDelegate & ProtocolTwoDelegate)?
您现在可以使用这两种协议。
答案 1 :(得分:2)
在您的代码中,delegate
只是一个普通的属性。您可以使用多个协议声明具有相同名称和相同类型的属性,并让类直接或间接地实现它。
如果不同的协议定义了具有相同名称但类型不同的属性,则无法进行编译,因为编译器会抱怨重新声明属性和类不能确认其中一个协议。
有两种可能的解决方案。最明显的一个是避免使用在其他协议中使用的概率很高的名称 - delegate
是典型案例。使用其他命名约定,例如protocol1Delegate
,dataSourceDelegate
,apiCallDelegate
等。
第二种解决方案包括用方法替换属性。例如:
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个协议使用相同的函数签名(名称,参数和返回类型),则在类中实现时,您将实现该函数一次 - 在某些情况下可能是所需行为,但在其他情况下则不需要。
答案 2 :(得分:2)
解决方案可能是使用协议扩展(检查extension Combined
)。好处是Combined
仅声明delegate
和oneDelegate
和twoDelegate
计算交叉实施。不幸的是,要求将三个变量暴露在课堂外,这可能会带来不便。
// 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()