2015-01-28 3 views
2

В качестве упражнения я пытаюсь расширить Array в Swift, чтобы добавить функцию члена sum(). Это должно быть безопасным по типу, чтобы я хотел позвонить sum() для компиляции только в том случае, если массив содержит элементы, которые могут быть добавлены.Ограничения обобщенного типа с помощью Swift

Я попробовал несколько вариантов что-то вроде этого:

extension Array { 

    func sum<U : _IntegerArithmeticType where U == T>() -> Int { 
     var acc = 0 
     for elem in self { 
      acc += elem as Int 
     } 
     return acc 
    } 

} 

Идея состояла в том, чтобы сказать: «Хорошо, что это общая функция, общий тип должен быть чем-то вроде Int, а также должны быть то же, что и T, тип элементов массива ". Но компилятор жалуется: «Требование одного типа делает общие параметры U и T эквивалентными». Правильно, и они должны быть с дополнительными ограничениями T : _IntegerArithmeticType.

Почему компилятор не разрешает мне это делать? Как мне это сделать?

(я знаю, что я должен позже исправить, как вещи складываются и то, что возвращаемый тип точно есть, но я застрял на тип ограничения на данный момент.)

+0

В настоящее время невозможно расширить массив с помощью методов, для которых элементы должны иметь ограниченный тип. Сравните http://stackoverflow.com/questions/24938948/array-extension-to-remove-object-by-value или http://stackoverflow.com/questions/25630476/swift-array-insert-generics (оба из них может квалифицироваться как дубликат). –

+0

Вы писали: «(в настоящее время)». Кто-нибудь слышал шепот, что он может скоро измениться? –

+0

Я * думаю *, что я прочитал в devforums.apple.com, что это известная проблема и может измениться в будущем, но я не уверен на 100%. Я дам вам ссылку, если найду ее снова. –

ответ

3

Согласно комментарий Мартина АиР, это в настоящее время невозможно. Дело в том, что я искушению использовать в данной ситуации было бы явное принятие функции в T -> Int преобразования:

extension Array { 

    func sum(toInt: T -> Int?) -> Int { 
     var acc = 0 
     for elem in self { 
      if let i = toInt(elem) { 
       acc += i 
      } 
     } 
     return acc 
    } 

} 

Тогда я могу написать такие вещи, как это:

func itself<T>(t: T) -> T { 
    return t 
} 

let ss = ["1", "2", "3", "4", "five"].sum { $0.toInt() } 
let si = [1, 2, 3, 4].sum(itself) 

Явная функция должна однако, пройдены. Разумеется, часть (itself) может быть заменена на { $0 }. (Другие называют itself функцию identity.)

Обратите внимание, что A -> B функция может быть принят, когда A -> B? требуется.

Смежные вопросы