Возможно ли сделать расширение Array в Swift, которое ограничено одним classом?

Могу ли я сделать расширение массива, которое применяется, например, только к строкам?

Начиная с Swift 2, это может быть достигнуто с помощью расширений протокола , которые обеспечивают реализацию методов и свойств для соответствующих типов (необязательно ограниченных дополнительными ограничениями).

Простой пример: Определите метод для всех типов, соответствующих SequenceType (например, Array ), где элементом последовательности является String :

 extension SequenceType where Generator.Element == String { func joined() -> String { return "".join(self) } } let a = ["foo", "bar"].joined() print(a) // foobar 

Метод расширения не может быть определен для struct Array напрямую, но только для всех типов, соответствующих некоторому протоколу (с дополнительными ограничениями). Поэтому нужно найти протокол, к которому Array и который предоставляет все необходимые методы. В приведенном выше примере это SequenceType .

Другой пример (вариант Как вставить элемент в правильное положение в отсортированный массив в Swift? ):

 extension CollectionType where Generator.Element : Comparable, Index : RandomAccessIndexType { typealias T = Generator.Element func insertionIndexOf(elem: T) -> Index { var lo = self.startIndex var hi = self.endIndex while lo != hi { // mid = lo + (hi - 1 - lo)/2 let mid = lo.advancedBy(lo.distanceTo(hi.predecessor())/2) if self[mid] < elem { lo = mid + 1 } else if elem < self[mid] { hi = mid } else { return mid // found at position `mid` } } return lo // not found, would be inserted at position `lo` } } let ar = [1, 3, 5, 7] let pos = ar.insertionIndexOf(6) print(pos) // 3 

Здесь метод определяется как расширение для CollectionType потому что необходим доступ к элементам подстроки, а элементы должны быть Comparable .

ОБНОВЛЕНИЕ: см. Ниже ответ Martin для обновлений Swift 2.0. (Я не могу удалить этот ответ, так как он принят, если Дуг может принять ответ Мартина, я удалю его, чтобы избежать путаницы в будущем).


Это на несколько раз появилось на форумах, и ответ отрицательный, вы не можете сделать это сегодня, но они понимают, что это проблема, и они надеются улучшить это в будущем. Есть вещи, которые они хотели бы добавить в stdlib, которые также нуждаются в этом. Вот почему так много бесплатных функций stdlib. Большинство из них являются обходными задачами для этой проблемы или проблемы «не по умолчанию» (т. Е. «Черты» или «mixins»).

На это уже ответили три мудреца выше ;-), но я смиренно предлагаю обобщение ответа @ Мартина. Мы можем настроить таргетинг на произвольный class, используя протокол «маркер», который реализуется только в classе, который мы хотим настроить. То есть. не нужно искать протокол, но может создать тривиальный для использования в таргетинге на нужный class.

 protocol TargetType {} extension Array:TargetType {} struct Foo { var name:String } extension CollectionType where Self:TargetType, Generator.Element == Foo { func byName() -> [Foo] { return sort { l, r in l.name < r.name } } } let foos:[Foo] = ["c", "b", "a"].map { s in Foo(name: s) } print(foos.byName()) 

Вы все еще не использовали прецедентов, несмотря на множество запросов в комментариях, поэтому трудно понять, что вам нужно. Но, как я уже сказал в комментарии (и Роб сказал в ответ), вы не получите его буквально; расширения не работают таким образом (на данный момент).

Как я уже сказал в комментарии, то, что я сделал бы, это обернуть массив в структуру. Теперь структура защищает и гарантирует тип строки, и у нас есть инкапсуляция. Вот пример, хотя, конечно, вы должны помнить, что вы не указали на то, что вам действительно хотелось бы сделать, поэтому это может быть не совсем удовлетворительным:

 struct StringArrayWrapper : Printable { private var arr : [String] var description : String { return self.arr.description } init(_ arr:[String]) { self.arr = arr } mutating func upcase() { self.arr = self.arr.map {$0.uppercaseString} } } 

И вот как это назвать:

  let pepboys = ["Manny", "Moe", "Jack"] var saw = StringArrayWrapper(pepboys) saw.upcase() println(saw) 

Таким образом, мы эффективно изолировали наш массив строк в мире, где мы можем вооружить его функциями, которые применяются только к строковым массивам. Если pepboys не были строковым массивом, мы не могли бы обернуть его в StringArrayWrapper для начала.

  • Как использовать realloc в функции в C
  • Массив сортировки Javascript по двум полям
  • Как лучше всего обрабатывать динамические многомерные массивы в C / C ++?
  • Java два varargs одним способом
  • Как найти индекс элемента списка в Swift?
  • Java читает файл и сохраняет текст в массиве
  • Создание массива из диапазона в VBA
  • Репликация массива по элементам в Matlab
  • Что делает объект jQuery отображаться как массив в инструментах разработчика Chrome?
  • Алгоритм перестановки для массива целых чисел в Java
  • Передача многомерного массива переменной длины в функцию
  • Interesting Posts

    Android L’Ripple Effect – Touch Feedback для кнопок – использование XML

    Как модемная сеть работает в Virtualbox?

    Почему увеличение дерева свойств write_json сохраняет все как строку? Можно ли это изменить?

    Правильное закрытие SSLSocket

    Возможно ли отделить объект Hibernate, чтобы изменения объекта не были автоматически сохранены в базе данных?

    Нужна помощь в создании XSLT, у меня есть исходный и целевой XML

    Принудительный сценарий bash для выполнения до завершения, когда некоторые элементы могут

    Как создать отдельную подсеть для беспроводного доступа?

    Зачем мне нужно «hdparm -r», чтобы установить чтение / запись видеокамеры Sony и почему это опасно?

    Изменение временных рядов данных с широкоформатного формата (для печати)

    {Debian} Отключение и повреждение внешнего диска при загрузке больших файлов с помощью файла seafile

    для оптимизации цикла

    Как отключить значок «Получить Windows 10» в области уведомлений (лоток)?

    Подключите два компьютера к одному динамику?

    Как отсортировать столбец данных DataGridView?

    Давайте будем гением компьютера.