Hàm tổng quát
Thuộc phần Lập trình hướng đối tượng trong hành trình Swift của Coddy. Bài học 34 trên 57.
Một hàm tổng quát có thể làm việc với mọi kiểu dữ liệu. Phần giữ chỗ trong dấu ngoặc nhọn, thường là T, đại diện cho kiểu dữ liệu mà bên gọi sử dụng, và Swift sẽ xác định kiểu đó mỗi khi gọi hàm:
func firstAndLast<T>(_ items: [T]) -> [T] {
guard let first = items.first, let last = items.last else { return [] }
return [first, last]
}
print(firstAndLast([3, 8, 1]))
print(firstAndLast(["a", "b", "c"]))Đầu ra:
[3, 1]
["a", "c"]Bên trong hàm, không có thông tin nào về T, nên chỉ được dùng những thao tác hoạt động với mọi kiểu dữ liệu. Một ràng buộc như T: Comparable cho phép dùng thêm nhiều thao tác, ở đây là toán tử <:
func largest<T: Comparable>(_ items: [T]) -> T? {
guard var best = items.first else { return nil }
for item in items where item > best { best = item }
return best
}
print(largest([4, 9, 2])!)
print(largest(["pear", "apple", "zucchini"])!)Đầu ra:
9
zucchiniKiểu tổng quát giữ nguyên kiểu chính xác, không như Any. Kết quả của largest trên [Int] có kiểu Int?, nên bạn có thể dùng trong phép tính số học mà không cần ép kiểu:
func largest<T: Comparable>(_ items: [T]) -> T? {
items.max()
}
let top = largest([3, 7, 5]) ?? 0
print(top * 10)Đầu ra:
70Một hàm có thể có nhiều kiểu giữ chỗ, và các ràng buộc có thể gọi tên những giao thức do bạn tự định nghĩa:
protocol Scored { var score: Int { get } }
struct Player: Scored { let name: String; let score: Int }
struct Team: Scored { let score: Int }
func total<T: Scored>(_ items: [T]) -> Int {
items.reduce(0) { $0 + $1.score }
}
func pair<A, B>(_ a: A, _ b: B) -> String { "\(a) & \(b)" }
print(total([Player(name: "a", score: 3), Player(name: "b", score: 4)]))
print(total([Team(score: 10)]))
print(pair(1, "one"))Đầu ra:
7
10
1 & oneThử thách
DễHãy viết hàm tổng quát countWhere(_:_:), nhận một mảng có phần tử thuộc bất kỳ kiểu dữ liệu nào và một vị từ (T) -> Bool, rồi trả về số phần tử thỏa mãn vị từ đó. Hãy viết hàm mostCommon(_:), nhận một mảng có phần tử thuộc bất kỳ kiểu Hashable nào và trả về phần tử xuất hiện nhiều nhất. Nếu số lần xuất hiện bằng nhau, hàm trả về phần tử xuất hiện đầu tiên trong mảng. Nếu mảng rỗng, hàm trả về nil.
Code được cung cấp đọc một dòng gồm các từ được phân tách bằng dấu phẩy và một dòng gồm các số. Code in ra số từ dài hơn 3 ký tự, từ xuất hiện nhiều nhất, số lượng số chẵn và số xuất hiện nhiều nhất.
Đặt code của bạn trong Functions.swift. main.swift chứa code đầu vào và đầu ra được cung cấp, bạn không thể chỉnh sửa tệp này.
Tự làm thử
// Đoạn code đầu vào/đầu ra đã được cung cấp: giữ nguyên như hiện tại
var input: [String] = []
while let line = readLine() { input.append(line) }
let words = input[0].split(separator: ",").map(String.init)
let numbers = input[1].split(separator: ",").map { Int($0)! }
print(countWhere(words) { $0.count > 3 })
print(mostCommon(words) ?? "none")
print(countWhere(numbers) { $0 % 2 == 0 })
print(mostCommon(numbers).map { String($0) } ?? "none")
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Lớp và đối tượng
Làm việc với tệpĐịnh nghĩa lớpPhương thức và selfHàm khởi tạoLớp là tham chiếuÔn tập: Thẻ thư viện2Struct và kiểu giá trị
StructNgữ nghĩa giá trịPhương thức thay đổiStruct hay classÔn tập: mặt hàng trong kho5Kế thừa
Lớp conGhi đè phương thứcHàm khởi tạo và superfinal và hệ phân cấpÔn tập: hệ phân cấp nhân viên8Các giao thức tiêu chuẩn
CustomStringConvertibleEquatableComparableHashableÔn tập: Sắp xếp tùy chỉnhTự luyện tập: Playground Swift