我做了一个协议字符串化,将实现协议的类型转换为字符串。

protocol Stringify {
    func stringify() -> String
}

extension Collection where Iterator.Element == Stringify {
    /// changes all the elements in the collection to a String
    func stringify() -> [String] {
        var strings = [String]()
        if let elements = self as? [Stringify] {
            for element in elements {
                strings.append(element.stringify())
            }
        }
        return strings
    }
}

extension Int: Stringify {
    func stringify() -> String {
        return String(self)
    }
}

extension Double: Stringify {
    func stringify() -> String {
        return String(self)
    }
}


let test = [5,6,7]

/// does work
[6,5,34].stringify()


/// does not work -> Error alert
test.stringify()

但是,当我将int集合设置为属性并对其使用then stringify()时,它不起作用。
错误:
在“collection”上引用实例方法“stringify()”需要
类型“int”和“stringify”等效
如果我直接使用,一切都会好起来的。
这里有什么问题?

最佳答案

extension Collection where Iterator.Element == Stringify

具有“相同类型要求”,并为其元素属于类型Stringify的集合定义扩展。但是test是一个Int数组,即元素符合Stringify协议。所以你想要的是
extension Collection where Iterator.Element : Stringify

或者,等价地,
extension Collection where Element : Stringify

原因是
/// does work
[6,5,34].stringify()

用您的原始定义编译是编译器从上下文推断数组的类型为[Stringify]
let test: [Stringify] = [5,6,7]
test.stringify()

也可以编译。
注意,在扩展方法中不需要强制转换self。您可以将实现简化为
func stringify() -> [String] {
    var strings = [String]()
    for element in self {
        strings.append(element.stringify())
    }
    return strings
}

或者只是
func stringify() -> [String] {
    return self.map { $0.stringify() }
}

关于swift - 在'Collection'上引用实例方法'stringify()'要求类型'Int'和'Stringify'是等价的,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56988636/

10-09 16:19