Множественные ограничения типов в Swift
Скажем, у меня есть эти протоколы:
protocol SomeProtocol {
}
protocol SomeOtherProtocol {
}
Теперь, если мне нужна функция, которая принимает общий тип, но этот тип должен соответствовать SomeProtocol
, я мог бы сделать:
func someFunc<T: SomeProtocol>(arg: T) {
// do stuff
}
Но есть ли способ добавить ограничение типа для нескольких протоколов?
func bothFunc<T: SomeProtocol | SomeOtherProtocol>(arg: T) {
}
Аналогичные вещи используют запятые, но в этом случае он начнет объявление другого типа. Вот что я пробовал.
<T: SomeProtocol | SomeOtherProtocol>
<T: SomeProtocol , SomeOtherProtocol>
<T: SomeProtocol : SomeOtherProtocol>
Ответы
Ответ 1
Вы можете использовать where where, который позволяет указать столько требований, сколько вы хотите (все это должно быть выполнено), разделенные запятыми
Swift 2:
func someFunc<T where T:SomeProtocol, T:SomeOtherProtocol>(arg: T) {
// stuff
}
Swift 3 и 4:
func someFunc<T: SomeProtocol & SomeOtherProtocol>(arg: T) {
// stuff
}
или более мощное предложение where:
func someFunc<T>(arg: T) where T:SomeProtocol, T:SomeOtherProtocol{
// stuff
}
Вы можете, конечно, использовать состав протокола (например, protocol<SomeProtocol, SomeOtherProtocol>
), но он немного менее гибкий.
Использование where
позволяет обрабатывать случаи, когда задействованы несколько типов.
Вы все равно можете составлять протоколы для повторного использования в нескольких местах или просто предоставить составленному протоколу значащее имя.
Ответ 2
У вас есть две возможности:
-
Вы используете где предложение, как указано в ответе Jiaaro:
func someFunc<T where T : SomeProtocol, T : SomeOtherProtocol>(arg: T) {
// do stuff
}
-
Вы используете
Ответ 3
В эволюцию Swift 3.0 внесены некоторые изменения. Теперь наши два варианта выглядят немного иначе.
Использование предложения where
в Swift 3.0:
Предложение where
теперь перемещено в конец сигнатуры функции для улучшения удобочитаемости. Таким образом, наследование нескольких протоколов теперь выглядит следующим образом:
func someFunc<T>(arg: T) where T:SomeProtocol, T:SomeOtherProtocol {
}
Использование конструкции protocol<>
в Swift 3.0:
Композиция, использующая конструкцию protocol<>
, устарела. Раньше protocol<SomeProtocol, SomeOtherProtocol>
теперь выглядит следующим образом:
func someFunc<T:SomeProtocol & SomeOtherProtocol>(arg: T) {
}
Ссылки.
Дополнительная информация об изменениях для where
находится здесь: https://github.com/apple/swift-evolution/blob/master/proposals/0081-move-where-expression.md
И больше об изменениях для конструкции протокола < > приведены здесь: https://github.com/apple/swift-evolution/blob/master/proposals/0095-any-as-existential.md
Ответ 4
Swift 3 предлагает до 3 различных способов объявить вашу функцию.
protocol SomeProtocol {
/* ... */
}
protocol SomeOtherProtocol {
/* ... */
}
1. Используя оператор &
func someFunc<T: SomeProtocol & SomeOtherProtocol>(arg: T) {
/* ... */
}
2. Используя предложение where
func someFunc<T>(arg: T) where T: SomeProtocol, T: SomeOtherProtocol {
/* ... */
}
3. Используя оператор where
и &
оператор
func someFunc<T>(arg: T) where T: SomeProtocol & SomeOtherProtocol {
/* ... */
}
Также обратите внимание, что вы можете использовать typealias
, чтобы сократить объявление функции.
typealias RequiredProtocols = SomeProtocol & SomeOtherProtocol
func someFunc<T: RequiredProtocols>(arg: T) {
/* ... */
}