( Swift 2.x )
Bạn cũng có thể mở rộng mảng để tuân thủ giao thức chứa màu xanh lam cho các phương thức kiểu chung, ví dụ: giao thức chứa các tiện ích chức năng tùy chỉnh của bạn cho tất cả các thành phần mảng chung tuân theo một số ràng buộc kiểu, giao thức nói MyTypes
. Phần thưởng khi sử dụng phương pháp này là bạn có thể viết các hàm lấy các đối số mảng chung, với một ràng buộc là các đối số mảng này phải tuân theo giao thức tiện ích chức năng tùy chỉnh của bạn, giao thức nóiMyFunctionalUtils
.
Bạn có thể nhận được hành vi này một cách ngầm định, bằng cách gõ ràng buộc các phần tử mảng MyTypes
, hoặc --- như tôi sẽ trình bày trong phương thức tôi mô tả bên dưới ---, khá gọn gàng, rõ ràng, để tiêu đề hàm chung chung của bạn hiển thị trực tiếp các mảng đầu vào phù hợp với MyFunctionalUtils
.
Chúng tôi bắt đầu với các Giao thức MyTypes
để sử dụng như ràng buộc kiểu; mở rộng các loại bạn muốn phù hợp với khái quát của bạn bằng giao thức này (ví dụ bên dưới mở rộng các loại cơ bản Int
và Double
cũng như một loại tùy chỉnh 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)
}
Giao thức MyFunctionalUtils
(giữ bản thiết kế chi tiết các tiện ích chức năng mảng chung bổ sung của chúng tôi) và sau đó, phần mở rộng của Array bằng MyFunctionalUtils
; thực hiện phương pháp in màu xanh:
/* 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
}
}
Cuối cùng, các thử nghiệm và hai ví dụ cho thấy một hàm lấy các mảng chung, với các trường hợp sau, tương ứng
Hiển thị xác nhận ngầm định rằng các tham số mảng phù hợp với giao thức 'MyFeftalUtils', thông qua kiểu ràng buộc các thành phần mảng thành 'MyTypes' (hàm bar1
).
Hiển thị rõ ràng rằng các tham số mảng tuân thủ giao thức 'MyFactoralUtils' (chức năng bar2
).
Bài kiểm tra và ví dụ sau:
/* 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[]
bit khi nhấp vào Lệnh trên loại Mảng trong XCode, nhưng không thấy bất kỳ cách nào để thực hiện nó mà không gặp lỗi.