Swift Generics проблема

Прямо сейчас я хочу видеть, включен ли объект в Array так:

func isIncluded<U:Comparable>(isIncluded : U) -> Bool
{
    for item in self
    {
        if (item == isIncluded)
        {
            return true
        }
    }

    return false
}

Если вы заметили, что эта функция принадлежит Array расширение. Проблема в том, если добавить это к этому:

extension Array{

}

Я получаю следующую ошибку:

Не удалось найти перегрузку для '==', которая принимает предоставленные аргументы

введите описание изображения здесь

Я понимаю, что, возможно, мне нужно будет сказать, какие объекты должны быть внутри Array вот так: T[] <T.GeneratorType.Element: Comparable>, Но это не так хорошо работает:

Скрепленный блок выписок является неиспользованным закрытием
Неноминальный тип 'T[]' не может быть расширен
Ожидаемое '{' в расширении

введите описание изображения здесь

3 ответа

Решение

С Swift нам нужно подумать, есть ли функция, которая может добиться цели - вне методов класса.

Так же, как в нашем случае здесь:

contains(theArray, theItem)

Вы можете попробовать это на детской площадке:

let a = [1, 2, 3, 4, 5]
contains(a, 3)
contains(a, 6)

Я обнаружил множество этих функций, щелкнув cmd по символу Swift (например, Array), а затем просмотрев этот файл (который представляется глобальным файлом, содержащим все объявления для общих классов и функций Swift).

Вот небольшое расширение, которое добавит метод "содержащий" ко всем массивам:

extension Array {
    func contains<T: Equatable>(item: T) -> Bool {
        for i in self {
            if item == (i as T) { return true }
        }
        return false
    }
}

Чтобы добавить, проблема в том, что T уже определено, и определение массива T не соответствует Equatable. Вы можете либо выполнить то, что вы хотите, разыгрывая (например, принятый ответ) и рискуя недействительным приведением, либо вы можете передать делегата, где не требуется разыгрывание.

Рассмотрите возможность изменения следующим образом:

extension Array {
   func contains(comparator: (T)->Bool) -> Bool {
    for item in self {
        if comparator(item) {
           return true
        }
    }
    return false
  }
}

Пример использования:

class Test {
    func arrayContains(){
        var test: Int[] = [0,1,3,4,5]
        //should be true 
        var exists = test.contains({(item)->Bool in item == 0});
    }
}

Не сказать, что это невозможно, но я еще не видел способа расширить структуры или классы, чтобы наложить условия на оригинальные дженерики, например, чтобы гарантировать Equatable или же Comparable на массиве. Однако для вашей конкретной проблемы вместо расширения вы можете сделать что-то вроде следующего:

var arr = [1, 2, 3]
var isIncluded : Bool = arr.bridgeToObjectiveC().doesContain(1) 
Другие вопросы по тегам