Khi viết chức năng chung, đôi khi dễ dàng tiếp cận nó theo 3 bước: trước tiên hãy viết mã độc lập bằng cách sử dụng một loại cụ thể. Sau đó viết mã như một hàm, vẫn còn với một kiểu cụ thể. Cuối cùng, thay đổi hàm thành generic.
Phần thứ nhất, chia một mảng 3, có thể được thực hiện như thế này:
let a = [1,2,3,4,5]
// map is run on the array of integers, and returns a new
// array with the operation performed on each element in a:
let b = a.map { $0/3 }
// so b will be [0,0,1,1,1]
// (don’t forget, integer division truncates)
Lưu ý việc đóng cửa mà bạn cung cấp giữa { }
là một hoạt động mà sẽ được áp dụng cho từng yếu tố của mảng . $0
đại diện cho phần tử, và bạn chia nó cho 3. Bạn cũng có thể viết nó như là a.map { i in i/3 }
.
Để đưa điều này vào chức năng riêng của nó:
func divideby3Map(source: [Int]) -> [Int] {
return source.map { $0/3 }
}
Không cần phải khai báo một mảng tươi - map
sẽ tạo cho bạn. Sau đó, bạn có thể trả lại trực tiếp (bạn có thể gán nó tạm thời nếu bạn thích, nhưng điều đó không thực sự cần thiết).
Cuối cùng, nếu bạn muốn làm cho nó chung chung, hãy bắt đầu bằng cách thêm một giữ chỗ:
func divideby3Map<T>(source: [T]) -> [T] {
return source.map { $0/3 }
}
Lưu ý, chỉ có một nhu cầu cho một placeholder, T
, bởi vì bạn đang quay trở lại cùng loại chính xác mà bạn được thông qua in.
Ngoại trừ ... điều này sẽ không biên dịch, vì trình biên dịch không biết rằng T
được đảm bảo cung cấp hai điều quan trọng: khả năng phân chia (toán tử /
) và khả năng tạo mới T
từ số nguyên literals (tức là để tạo ra một T
với giá trị 3
để chia cho). Nếu không, điều gì sẽ xảy ra nếu chúng ta truyền một mảng các chuỗi hoặc một mảng các mảng?
Để thực hiện việc này, chúng tôi cần "hạn chế" T
để chức năng của chúng tôi chỉ chấp nhận làm loại đối số cung cấp các tính năng này. Một trong những giao thức chúng ta có thể sử dụng để hạn chế T
là IntegerType
, mà không đảm bảo các tính năng này (cũng như một số những người khác như +
, *
vv):
func divideby3Map<T: IntegerType>(source: [T]) -> [T] {
return source.map { $0/3 }
}
divideby3Map(a) // returns [0,0,1,1,1]
let smallInts: [UInt8] = [3,6,9]
divideby3Map(smallInts) // returns [1,2,3]
Nếu nó chỉ là toán học tại sao bạn không chỉ cần sử dụng Int hoặc tăng gấp đôi? –