在Swift 4中,你能编写一个仅适用于符合多种协议的扩展吗?

时间:2017-12-19 20:51:21

标签: swift protocols extension-methods swift4 swift-extensions

考虑这些协议

protocol NamedThing{
    var name:String{ get }
}

protocol ValuedThing{

    associatedtype ValueType

    var value:ValueType{ get }
}

这些结构......

struct TestThingA : NamedThing {
    let name = "TestThing"
}

struct TestThingB : ValuedThing {

    typealias ValueType = Int

    let value = 4
}

struct TestThingC : NamedThing, ValuedThing {

    typealias ValueType = Int

    let name = "TestThing"
    let value = 4
}

我正在尝试编写一个仅适用于struct TestThingC的扩展名,因为它符合这两种协议。

当然,这些都不起作用......

extension NamedThing & ValuedThing{
    func test(){
        print("Named thing \(name) has a value of \(value)")
    }
}

extension Any where NamedThing & ValuedThing {
    func test(){
        print("Named thing \(name) has a value of \(value)")
    }
}

extension Any where Self is NamedThing, Self is ValuedThing{

    func test(){
        print("Named thing \(name) has a value of \(value)")
    }
}

extension Any where Self == NamedThing, Self == ValuedThing{

    func test(){
        print("Named thing \(name) has a value of \(value)")
    }
}

那么如何编写适用于符合两种(多种)协议的项目的扩展名?

2 个答案:

答案 0 :(得分:4)

您可以为其中一个协议定义受限扩展名:

extension NamedThing where Self: ValuedThing {
    func test(){
        print("Named thing \(name) has a value of \(value)")
    }
}

TestThingC().test() // compiles

TestThingA().test() // error: Type 'TestThingA' does not conform to protocol 'ValuedThing'
TestThingB().test() // error: Value of type 'TestThingB' has no member 'test'

答案 1 :(得分:1)

我总是通过创建一个继承其他协议的新协议来解决这些问题。

protocol NamedValueThing: NamedThing, ValuedThing { }
extension TestThingC: NamedValueThing { }

extension NamedValueThing {
    func test() {
        print("\(value) \(name)")
    }
}

//TestThingA().test() //error: value of type 'TestThingA' has no member 'test'
//TestThingB().test() //error: value of type 'TestThingB' has no member 'test'
TestThingC().test() //4 TestThing