在 'Collection' 上引用实例方法 'stringify()' 需要类型 'Int' 和 'Stringify' 是等效的

PaF*_*aFi 3 protocols swift

我制作了一个协议 Stringify 来将实现该协议的类型转换为字符串。

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()
Run Code Online (Sandbox Code Playgroud)

但是当我将一组 Int 设置为一个属性并在其上使用 then stringify() 时,它不起作用。

错误:

在 'Collection' 上引用实例方法 'stringify()' 需要类型 'Int' 和 'Stringify' 是等效的

如果我直接使用它,一切都会很好。

这里有什么问题?

Mar*_*n R 5

extension Collection where Iterator.Element == Stringify 
Run Code Online (Sandbox Code Playgroud)

具有“相同类型要求”并为其元素类型为 的集合定义扩展 Stringify。但test是数组Int,即元素符合Stringify协议。所以你想要的是

extension Collection where Iterator.Element : Stringify
Run Code Online (Sandbox Code Playgroud)

或者,等效地,

extension Collection where Element : Stringify
Run Code Online (Sandbox Code Playgroud)

原因是

/// does work
[6,5,34].stringify()
Run Code Online (Sandbox Code Playgroud)

使用您的原始定义进行编译是编译器[Stringify]根据上下文推断数组的类型。

let test: [Stringify] = [5,6,7]
test.stringify()
Run Code Online (Sandbox Code Playgroud)

也会编译。


请注意,无需self在扩展方法中进行强制转换。您可以将实现简化为

func stringify() -> [String] {
    var strings = [String]()
    for element in self {
        strings.append(element.stringify())
    }
    return strings
}
Run Code Online (Sandbox Code Playgroud)

要不就

func stringify() -> [String] {
    return self.map { $0.stringify() }
}
Run Code Online (Sandbox Code Playgroud)