Ссылка на метод экземпляра 'stringify ()' в 'Collection' требует, чтобы типы 'Int' и 'Stringify' были эквивалентными - PullRequest
2 голосов
/ 11 июля 2019

Я создал протокол 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()

Но когда я присваиваю свойству коллекцию Ints и использую затем stringify (), она не работает.

Ошибка:

Ссылка на метод экземпляра 'stringify ()' в 'Collection' требует типы 'Int' и 'Stringify' эквивалентны

Если я использую его напрямую, все идет хорошо.

В чем здесь проблема?

1 Ответ

2 голосов
/ 11 июля 2019
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() }
}
...