Я хотел бы расширить Array
чтобы добавить соответствие новому протоколу - но только для массивов, чьи элементы сами соответствуют определенному протоколу.
В более общем смысле, я хотел бы, чтобы типы (будь то протоколы или конкретные типы) с параметрами типа реализовывали протокол только тогда, когда параметры типа соответствуют определенным ограничениям.
Начиная с Swift 2.0 это кажется невозможным. Есть ли способ, которым я скучаю?
пример
Предположим, у нас есть Friendly
протокол:
protocol Friendly {
func sayHi()
}
Мы можем расширить существующие типы для его реализации:
extension String: Friendly {
func sayHi() {
print("Greetings from \(self)!")
}
}
"Sally".sayHi()
Мы также можем расширить Array
для реализации sayHi()
когда все его элементы являются Friendly
:
extension Array where Element: Friendly {
func sayHi() {
for elem in self {
elem.sayHi()
}
}
}
["Sally", "Fred"].sayHi()
На этом этапе тип [Friendly]
должен сам реализовать Friendly
, поскольку он соответствует требованиям протоколов. Тем не менее, этот код не компилируется:
extension Array: Friendly where Element: Friendly {
func sayHi() {
for elem in self {
elem.sayHi()
}
}
}
Сообщение об ошибке: "расширение типа" Массив "с ограничениями не может иметь условия наследования", что, похоже, окончательно закрывает дверь при таком прямом подходе.
Есть ли косвенный обходной путь? Какой-нибудь умный трюк, который я могу использовать? Возможно, есть способ расширения SequenceType
вместо Array
?
Рабочее решение позволит скомпилировать этот код:
let friendly: Friendly = ["Foo", "Bar"]
Обновление: это появилось в Swift 4.1, и это красота!
extension Array: Friendly where Element: Friendly
пример extension Array: Friendly where Element: Friendly
теперь компилируется, как указано в исходном вопросе.