Swift实现多个协议与委托
我想实现一个协议,它本身继承多个协议,都有一个委托成员。有没有干净的方式来做到这一点,而不需要为每个协议的委托使用不同的名称?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>?
}
在你的代码中,delegate
只是一个普通的属性。您可以拥有多个协议,声明具有相同名称和相同类型的属性,并有一个类直接或间接实现它。
如果不同的协议定义了一个具有相同名称但类型不同的属性,那么您将无法编译它,因为编译器会抱怨重新声明属性和类没有确认其中一个协议。
有2种可能的解决方案。最明显的是避免使用在其他协议中使用的概率很高的名称 - 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个协议使用相同的函数签名(名称,参数和返回类型),那么在类中实现时,您将实现该函数一次 - 在某些情况下可能是想要的行为,但在其他情况下可能不需要。
我真的很想避免让不同名称的代表出现,我已经做到了这一点,并且效果不佳。另外,我并不知道你可能会重载Swift中的函数返回值。但是,我试图超载的财产,并没有奏效。这意味着即使外部方法名称与内部相同,我仍然需要两个名称不同的属性来跟踪它们。 – robhasacamera 2014-11-23 18:29:28
解决方案可能是使用协议扩展(请检查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()
您应该能够将它们结合在一个:
var delegate: (ProtocolOneDelegate & ProtocolTwoDelegate)?
您现在可以使用这两种协议。
委托是符合协议的对象。我想不出为什么它有一个代表。 – vikingosegundo 2014-11-23 03:17:33
@vikingosegundo我可以看到你的观点,即委托属于实现而不是协议。目前我只是从协议中删除委托属性,并且只在实现中声明协议。如果你想发布这个作为答案,我会很乐意接受它。 – robhasacamera 2014-11-23 18:33:12