Подтвердить что ты не робот

Swift 2 добавить протокол к протоколам

Могу ли я добавить соответствие протокола протоколу через быстрое расширение?

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

Я хочу сделать MyData протокол равным по умолчанию (просто сравните ID)

extension MyData : Equatable { }

Но я получаю эту прекрасную ошибку:

"Расширение протокола" MyData "не может иметь условие наследования"

Поведение, которое я ищу, - это BananaData, соответствующая Equatable (протокол), поскольку он реализует протокол 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
}
4b9b3361

Ответ 1

Как говорится в сообщении об ошибке: расширение протокола не может иметь условие наследования. Вместо этого вы можете сделать наследование MyData наследовать от Equatable в исходной декларации.

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

Затем вы можете расширить добавление реализации == для типов, соответствующих MyData:

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

Однако я бы не рекомендовал этого! Если вы добавите больше свойств в соответствующие типы, их свойства не будут проверяться на равенство. Пример:

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 избыточность.

Ответ 2

Разве эта игровая площадка делает то, что вы хотите? Я сделал это на основе того, что я понимаю из Протокольно-ориентированное программирование в Swift из WWDC 2015.

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