首页 文章

Swift 2添加协议与协议的一致性

提问于
浏览
20

我可以通过快速扩展将协议一致性添加到协议中吗?

//Plain old protocol here
protocol MyData {
    var myDataID: Int { get }
}

我想默认使 MyData 协议相等(只需比较ID)

extension MyData : Equatable { }

但我得到了这个可爱的错误:

“协议的扩展'MyData'不能有继承子句”

我正在寻找的行为是符合Equatable(协议)的BananaData,因为它实现了MyData协议,它可以提供Equatable的默认实现

//This is the method to implement Equatable
func ==(lhs: MyData, rhs: MyData) -> Bool {
    return lhs.myDataID == rhs.myDataID
}

struct BananaData: MyData {
    var myDataID: Int = 1
}

func checkEquatable(bananaOne: BananaData, bananaTwo: BananaData) {
    //This compiles, verifying that BananaData can be compared
    if bananaOne == bananaTwo { }
    //But BananaData is not convertible to Equatable, which is what I want
    let equatableBanana = bananaOne as Equatable
    //I don't get the additional operations added to Equatable (!=)
    if bananaOne != bananaTwo { } //Error
}

2 回答

  • 2

    正如错误消息所示:协议的扩展不能具有继承子句 . 相反,您可以在原始声明中使 MyData 协议从 Equatable 继承 .

    protocol MyData: Equatable {
        var myDataID: Int { get }
    }
    

    然后,您可以为符合 MyData 的类型添加 == 的实现:

    func == <T: MyData>(lhs: T, rhs: T) -> Bool {
        return lhs.myDataID == rhs.myDataID
    }
    

    但是, I would highly not recommend this! 如果向符合类型添加更多属性,则不会检查其属性是否相等 . 举个例子:

    struct SomeData: MyData {
        var myDataID: Int
        var myOtherData: String
    }
    
    let b1 = SomeData(myDataID: 1, myOtherData: "String1")
    let b2 = SomeData(myDataID: 1, myOtherData: "String2")
    
    b1 == b2 // true, although `myOtherData` properties aren't equal.
    

    在上面的情况中,您需要为 SomeData 覆盖 == 以获得正确的结果,从而使 == 接受 MyData 冗余 .

  • 23

    这个游乐场能做你想做的吗?我是根据我从WWDC 2015的Protocol-Oriented Programming in Swift了解到的 .

    import Foundation
    
    //Plain old protocol here
    
    func == (lhs: MyData, rhs: MyData) -> Bool {
        return lhs.myDataID == rhs.myDataID
    }
    
    func != (lhs: MyData, rhs: MyData) -> Bool {
        return lhs.myDataID != rhs.myDataID
    }
    
    protocol MyData {
        var myDataID: Int { get }
    }
    
    extension MyData where Self: Equatable {
    
    }
    
    
    struct BananaData: MyData {
        var myDataID: Int = 1
    }
    
    func checkEquatable(bananaOne: BananaData, bananaTwo: BananaData) {
        //This compiles, verifying that BananaData can be compared
        if bananaOne == bananaTwo {
            print("Same")
        }
        //But BananaData is not convertible to Equatable, which is what I want
        //I don't get the additional operations added to Equatable (!=)
        print(bananaOne.myDataID)
        print(bananaTwo.myDataID)
    
    
        if bananaOne != bananaTwo {
    
        }
    
        //Error
    
    
    }
    
    let b1 = BananaData(myDataID: 2)
    let b2 = BananaData(myDataID: 2)
    
    checkEquatable(b1, bananaTwo: b2)
    
    let c = b1 == b2  // Evaluates as true
    

相关问题