Menu
CoddyTech

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
zucchini

Kiể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:

70

Mộ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 & one
challenge icon

Thử 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")
quiz iconTự kiểm tra

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

Tự luyện tập: Playground Swift