В вашем примере T представляет собой тип. И как только этот тип будет согласован для всей функции.
func swapTwoValues<T>(inout a: T, inout b: T) {
let temporaryA = a
a = b
b = temporaryA
}
Если T является Int в случае параметра а, то он также должен быть Int в случае параметра Ь. Как показано в этом использовании функции:
var valueA = 2
var valueB = 4
swapTwoValues(&valueA, b: &valueB)
valueA // 4
valueB // 2
Мы не могли поменять местами строки для Int, например, или даже Int для двойной, но до тех пор, как типы одинаковы, то этот общий метод будет принимать какие-либо Тип, потому что он безудержный во всех других отношениях.
var valueA = "Hello"
var valueB = "Swift"
swapTwoValues(&valueA, b: &valueB)
valueA // "Swift"
valueB // "Hello"
Это, однако, не означает, что многие функции исключены из общих функций. Вам просто нужно назначить другую букву для представления разных типов (используемая буква не имеет значения, T просто используется, потому что она является первой буквой типа, но нет причин, по которой она не может быть заменена Q, например, или любым другое письмо):
func swapTwoValues<T,S>(inout a: T, inout b: T, inout c: S, inout d: S) {
let temporaryA = a
a = b
b = temporaryA
let temporaryC = c
c = d
d = temporaryC
}
var valueA = 2
var valueB = 4
var valueC = "Hello"
var valueD = "Swift"
swapTwoValues(&valueA, b: &valueB, c:&valueC, d:&valueD)
valueA // 4
valueB // 2
valueC // "Swift"
valueD // "Hello"
Примечание: мы не можем обменять T для S, потому что Swift является строго типизированным языком, и у нас нет никакой уверенности, они одинаковы.
Это становится более интересным, когда протоколы участвуют, чтобы ограничить общие типы. Здесь я делаю это с UnsignedIntegerType:
func swapTwoValues<T: UnsignedIntegerType>(inout a: T, inout b: T) {
let temporaryA = a
a = b
b = temporaryA
}
var valueA:UInt = 10
var valueB:UInt = 11
swapTwoValues(&valueA, b: &valueB)
Теперь только такие типы, как UInt, Uint8, UInt32, и т.д., являются приемлемыми, а все остальные значения будут отклонены и создать ошибку.
Примечание. Причина ограничения типов с использованием протоколов заключается в том, что определенные методы могут быть гарантированы. Например, если для создания экземпляра нового типа требуется общая функция, тогда она должна принять протокол с методом init. (Вы можете проверить принятие протокола для каждого типа в документах Apple.)
Мы можем пойти дальше и использовать where
ключевое слово для определения типов, содержащихся в общей коллекции:
func swapTwoValues<T: CollectionType where T.Generator.Element: UnsignedIntegerType>(inout a: T, inout b: T) {
let temporaryA = a
a = b
b = temporaryA
}
var valueA:[UInt] = [10,12,4]
var valueB:[UInt] = [11,45,67]
swapTwoValues(&valueA, b: &valueB)
valueA // [11, 45, 67]
valueB // [10, 12, 4]
Или сделать что-то вроде проверки, что второй тип эквивалентен типу элементов в коллекции используя ==
:
func swapTwoValues<T: CollectionType, S where S == T.Generator.Element>(inout a: T, inout b: T, inout c: S, inout d: S) {
let temporaryA = a
a = b
b = temporaryA
let temporaryC = c
c = d
d = temporaryC
}
Дальнейшее чтение: Вещи становятся еще более интересными с protocol extensions in Swift 2, потому что теперь общие функции могут взять на себя характеристики методов типа, что делает их далеко м руды можно обнаружить.
Отличный вопрос, вы должны рассмотреть возможность выбора ответа на этот вопрос, если вы удовлетворите свой вопрос! Это улучшает качество вашего сообщения и, таким образом, помогает сообществу. –