违反协议规约-最佳做法

时间:2019-03-15 12:50:32

标签: swift protocols

我有一个代码(swift 4.2.1,xcode 10.1),给出了“冲突的一致性”编译错误。

应该如何重写它,做这种事情的最佳实践是什么?

代码应支持使用文本搜索来过滤字符串或复杂对象的数组...

protocol FilterableByText{
    func filter<T: StringProtocol>(by text:T) -> Self
    var isEmpty:Bool {get}
}

protocol ContainsString{
    func contains<T>(_ substring: T) -> Bool where T : StringProtocol
}

extension Array: FilterableByText where Element:ContainsString{
    func filter<T: StringProtocol>(by text:T) -> Array{
        return filter{$0.contains(text)}
    }
}

extension Array: FilterableByText where Element:FilterableByText{ // conflicting conformance
    func filter<T: StringProtocol>(by text:T) -> Array{
        return map{$0.filter(by: text)}.filter{!$0.isEmpty}
    }
}

2 个答案:

答案 0 :(得分:2)

代替尝试具有单独的一致性,您可以做的是创建具有不同约束的所需函数的单独实现。

protocol ContainsString {
    func contains<T>(_ substring: T) -> Bool where T: StringProtocol
}

extension Collection {
    func filter<T>(by text: T) -> [Element] where T: StringProtocol, Element: ContainsString {
        return filter { $0.contains(text) }
    }

    func filter<T>(by text: T) -> [Element] where T: StringProtocol, Element: Collection, Element.Element: ContainsString {
        return filter { !$0.filter(by: text).isEmpty }
    }
}

extension String: ContainsString {}

let strings = ["hello", "world"]
strings.filter(by: "hello") // ["hello"]

let stringOfStrings = [strings, ["foo", "bar"]]
stringOfStrings.filter(by: "hello") // ["hello", "world"]

答案 1 :(得分:0)

如编译器所建议的,冲突的一致性是不可接受的-行为将是不确定的,因为在扩展中没有解决冲突函数签名的规则。对于最佳实践,我想说的是为元素引入更多通用的但单一的协议,因此不会使您在默认扩展名中拆分逻辑: