(Swift 2.x)
您还可以扩展数组以使其符合用于泛型类型方法的包含blue-rpint的协议,例如,协议包含针对符合某种类型约束的所有泛型数组元素的自定义功能utils,例如protocol MyTypes
。使用这种方法的好处是,您可以编写带有通用数组参数的函数,但要约束这些数组参数必须符合您的自定义函数实用程序协议(例如protocol)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'(function 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[]
在Command上单击XCode中的Array类型时,看到的是相同的位,但是没有看到任何实现它的方法而没有收到错误。