Menu
CoddyTech

Đa hình

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 32 trên 57.

Tính đa hình nghĩa là một đoạn code có thể làm việc với các giá trị thuộc nhiều kiểu dữ liệu, và mỗi giá trị phản hồi theo cách riêng. Vòng lặp bên dưới gọi sound() mà không cần biết nó chứa con vật nào:

class Animal {
    func sound() -> String { "..." }
}
class Dog: Animal {
    override func sound() -> String { "Woof" }
}
class Cow: Animal {
    override func sound() -> String { "Moo" }
}

let farm: [Animal] = [Dog(), Cow(), Dog()]
for a in farm { print(a.sound()) }

Đầu ra:

Woof
Moo
Woof

Swift quyết định nên chạy cách triển khai nào tại thời điểm chạy, dựa trên đối tượng thực tế. Kiểu đã khai báo của biến không quan trọng; kiểu của đối tượng mới quan trọng:

class Animal {
    func sound() -> String { "..." }
}
class Cat: Animal {
    override func sound() -> String { "Meow" }
}

let pet: Animal = Cat()
print(pet.sound())

Đầu ra:

Meow

Protocol mang lại sự linh hoạt tương tự cho struct và enum. Ở đây, một hàm in ra mọi danh sách giá trị Drawable:

protocol Drawable {
    func draw() -> String
}
struct Line: Drawable {
    let length: Int
    func draw() -> String { String(repeating: "-", count: length) }
}
struct Box: Drawable {
    func draw() -> String { "[ ]" }
}

func render(_ items: [any Drawable]) -> String {
    items.map { $0.draw() }.joined(separator: " ")
}

print(render([Line(length: 3), Box(), Line(length: 1)]))

Đầu ra:

--- [ ] -

Đa hình thay thế các chuỗi if/switch dài để xử lý các loại đối tượng khác nhau. Thay vì hỏi một giá trị là gì rồi quyết định cần làm gì, bạn yêu cầu giá trị đó tự thực hiện. Thêm một loại mới nghĩa là thêm một kiểu mới, chứ không phải sửa mọi switch:

// không dùng tính đa hình (polymorphism)
if kind == "dog" { print("Woof") } else if kind == "cow" { print("Moo") }

// dùng tính đa hình
for animal in farm { print(animal.sound()) }
challenge icon

Thử thách

Dễ

Animal có name, legs() (4) và describe(), hàm này trả về Rex has 4 legs and says Woof, được tạo từ legs() và sound(). Khai báo Dog (âm thanh Woof), Bird (2 chân, âm thanh Tweet) và Snake (0 chân, âm thanh Hiss) bằng cách chỉ ghi đè legs() và sound().

Code được cung cấp đọc các dòng dog,Rex, bird,Pip hoặc snake,Kaa, lưu các con vật trong một mảng [Animal] và in ra describe() cho từng con.

Code của bạn nằm trong Animal.swift, Dog.swift, Bird.swift và Snake.swift. main.swift chứa code đầu vào/đầu ra được cung cấp và không thể chỉnh sửa.

Tự làm thử

// Đoạn code đầu vào/đầu ra đã được cung cấp: giữ nguyên
var input: [String] = []
while let line = readLine() { input.append(line) }
var zoo: [Animal] = []
for line in input {
    let p = line.split(separator: ",").map(String.init)
    switch p[0] {
    case "dog": zoo.append(Dog(name: p[1]))
    case "bird": zoo.append(Bird(name: p[1]))
    default: zoo.append(Snake(name: p[1]))
    }
}
for a in zoo { print(a.describe()) }
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