( Швидкий 2.x )
Ви також можете розширити масив відповідно до протоколу, що містить сині-rpints для методів загального типу, наприклад, протокол, що містить власні функціональні утиліти для всіх загальних елементів масиву, що відповідають деяким обмеженням типу, скажімо, протокол MyTypes. Бонус при використанні цього підходу полягає в тому, що ви можете записувати функції, використовуючи загальні аргументи масиву, з обмеженням, що ці аргументи масиву повинні відповідати вашому користувальницькому протоколу утиліти функції, скажімо, протоколу MyFunctionalUtils.
Ви можете отримати таку поведінку або неявно, ввівши обмеження елементів масиву до MyTypes, або --- як я покажу в описаному нижче методі ---, досить акуратно, явно, дозволяючи заголовку загальної функції масиву безпосередньо показувати, що вхідні масиви відповідає MyFunctionalUtils.
Ми починаємо з протоколів MyTypesдля використання як обмеження типу; розширити типи ви хочете , щоб вписатися в ваших дженериків з цього протоколу (наприклад , нижче розширює основні типи Intі Double, а також призначений для користувача тип MyCustomType)
/* Used as type constraint for Generator.Element */
protocol MyTypes {
var intValue: Int { get }
init(_ value: Int)
func *(lhs: Self, rhs: Self) -> Self
func +=(inout lhs: Self, rhs: Self)
}
extension Int : MyTypes { var intValue: Int { return self } }
extension Double : MyTypes { var intValue: Int { return Int(self) } }
// ...
/* Custom type conforming to MyTypes type constraint */
struct MyCustomType : MyTypes {
var myInt : Int? = 0
var intValue: Int {
return myInt ?? 0
}
init(_ value: Int) {
myInt = value
}
}
func *(lhs: MyCustomType, rhs: MyCustomType) -> MyCustomType {
return MyCustomType(lhs.intValue * rhs.intValue)
}
func +=(inout lhs: MyCustomType, rhs: MyCustomType) {
lhs.myInt = (lhs.myInt ?? 0) + (rhs.myInt ?? 0)
}
Протокол MyFunctionalUtils(тримає креслення наших додаткових загальних функцій масиву утиліти) і далі, розширення Array на MyFunctionalUtils; реалізація синьодрукованих методів:
/* Protocol holding our function utilities, to be used as extension
o Array: blueprints for utility methods where Generator.Element
is constrained to MyTypes */
protocol MyFunctionalUtils {
func foo<T: MyTypes>(a: [T]) -> Int?
// ...
}
/* Extend array by protocol MyFunctionalUtils and implement blue-prints
therein for conformance */
extension Array : MyFunctionalUtils {
func foo<T: MyTypes>(a: [T]) -> Int? {
/* [T] is Self? proceed, otherwise return nil */
if let b = self.first {
if b is T && self.count == a.count {
var myMultSum: T = T(0)
for (i, sElem) in self.enumerate() {
myMultSum += (sElem as! T) * a[i]
}
return myMultSum.intValue
}
}
return nil
}
}
Нарешті, тести та два приклади, що показують функцію, що приймає загальні масиви, з наступними випадками відповідно
Показано неявне твердження, що параметри масиву відповідають протоколу "MyFunctionalUtils", використовуючи тип обмеження елементів масивів на "MyTypes" (функція bar1).
Показано явно , що параметри масиву відповідають протоколу «MyFunctionalUtils» (функція bar2).
Випробування та приклади наступні:
/* Tests & examples */
let arr1d : [Double] = [1.0, 2.0, 3.0]
let arr2d : [Double] = [-3.0, -2.0, 1.0]
let arr1my : [MyCustomType] = [MyCustomType(1), MyCustomType(2), MyCustomType(3)]
let arr2my : [MyCustomType] = [MyCustomType(-3), MyCustomType(-2), MyCustomType(1)]
/* constrain array elements to MyTypes, hence _implicitly_ constraining
array parameters to protocol MyFunctionalUtils. However, this
conformance is not apparent just by looking at the function signature... */
func bar1<U: MyTypes> (arr1: [U], _ arr2: [U]) -> Int? {
return arr1.foo(arr2)
}
let myInt1d = bar1(arr1d, arr2d) // -4, OK
let myInt1my = bar1(arr1my, arr2my) // -4, OK
/* constrain the array itself to protocol MyFunctionalUtils; here, we
see directly in the function signature that conformance to
MyFunctionalUtils is given for valid array parameters */
func bar2<T: MyTypes, U: protocol<MyFunctionalUtils, _ArrayType> where U.Generator.Element == T> (arr1: U, _ arr2: U) -> Int? {
// OK, type U behaves as array type with elements T (=MyTypes)
var a = arr1
var b = arr2
a.append(T(2)) // add 2*7 to multsum
b.append(T(7))
return a.foo(Array(b))
/* Ok! */
}
let myInt2d = bar2(arr1d, arr2d) // 10, OK
let myInt2my = bar2(arr1my, arr2my) // 10, OK
extension T[]біт при натисканні на команду типу Array у XCode, але не бачити жодного способу його реалізації без отримання помилки.