Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift使用一个代理实现多个协议_Swift_Delegates_Protocols - Fatal编程技术网

Swift使用一个代理实现多个协议

Swift使用一个代理实现多个协议,swift,delegates,protocols,Swift,Delegates,Protocols,我正在尝试实现一个协议,该协议本身继承了多个协议,这两个协议都有一个委托成员。是否有一种干净的方法可以做到这一点,而不需要为每个协议的委托使用不同的名称 protocol ProtocolOne { var delegate: ProtocolOneDelegate? } protocol ProtocolTwo { var delegate: ProtocolTwoDelegate? } protocol CombinedProtocol: ProtocolOne, Pro

我正在尝试实现一个协议,该协议本身继承了多个协议,这两个协议都有一个委托成员。是否有一种干净的方法可以做到这一点,而不需要为每个协议的委托使用不同的名称

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>?
}
协议原型{
变量代理:ProtocolOneDelegate?
}
协议二{
变量委托:ProtocolTwoDelegate?
}
协议组合协议:ProtocolOne,Protocol2{
}
协议组合删除:ProtocolOneDelegate,ProtocolTwoDelegte{
}
类ProtocolImpl:CombinedProtocol{
//我如何在这里实现委托?
//我尝试了以下选项但没有成功:
变量代理:组合删除门?
var代理:协议?
}

在代码中,
委托
只是一个普通属性。可以使用多个协议声明具有相同名称和相同类型的属性,并使用一个类直接或间接实现该属性

如果不同的协议使用相同的名称但不同的类型定义了一个属性,您将无法使其编译,因为编译器将抱怨重新声明一个属性,而类不符合其中一个协议

有两种可能的解决方案。最明显的一点是避免使用在其他协议中使用概率很高的名称-
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考虑具有相同参数列表但返回类型不同的函数作为重载。但是请注意,如果两个协议使用相同的函数签名(名称、参数和返回类型),在类中实现时,您将实现该函数一次-在某些情况下,这可能是需要的行为,但在其他情况下是不需要的。

解决方案可能是使用协议扩展(检查
扩展组合
)。好处是
Combined
只声明
delegate
oneDelegate
twodedelegate
是跨实现计算的。不幸的是,要求将这三个变量暴露在类之外,这可能会带来不便

// 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我能理解你的观点,委托属于实现而不是协议。目前,我只是从协议中删除了委托属性,并且只在实现中声明了协议。如果你想把这个作为一个答案,我很乐意接受。我真的不想让代表们有各种各样的名字,我已经做过了,这已经是过去了,而且效果不好。另外,我不知道您可能会在Swift中重载返回函数。但是,我尝试了重载属性,但没有成功。这意味着,即使外部的方法名与内部的方法名相同,我仍然需要两个名称不同的属性来跟踪这两个属性。这是否存在编译器限制?我有一个稍微复杂一点的例子,
ProtocolImpl
,在本例中,充当委托本身,并将
delegate
属性重定向到self,而这不会编译。这里有一个例子。