Menu
CoddyTech

Tự động nâng phương thức

Thuộc phần Lập trình hướng đối tượng trong hành trình GO của Coddy. Bài học 36 trên 107.

Cũng như việc nhúng struct đưa các trường lên struct bên ngoài, Go cũng đưa các phương thức từ kiểu được nhúng lên. Điều này có nghĩa là bạn có thể gọi trực tiếp trên struct bên ngoài các phương thức được định nghĩa trong struct được nhúng.

type Engine struct {
    Horsepower int
}

func (e Engine) Start() string {
    return "Engine started"
}

type Car struct {
    Model string
    Engine  // nhúng
}

Vì Car nhúng Engine, phương thức Start() tự động được nâng lên:

func main() {
    c := Car{
        Model:  "Sedan",
        Engine: Engine{Horsepower: 200},
    }
    
    fmt.Println(c.Start())         // Engine đã khởi động
    fmt.Println(c.Engine.Start())  // Cũng hoạt động
}

Việc nâng cấp này có một hệ quả quan trọng đối với các giao diện. Nếu kiểu được nhúng thỏa mãn một giao diện, kiểu bên ngoài cũng tự động thỏa mãn giao diện đó:

type Starter interface {
    Start() string
}

func Ignite(s Starter) {
    fmt.Println(s.Start())
}

func main() {
    c := Car{Model: "Sedan", Engine: Engine{Horsepower: 200}}
    Ignite(c)  // Car đáp ứng giao diện Starter thông qua Engine
}

Kiểu Car không triển khai tường minh Starter, nhưng vẫn đáp ứng giao diện này vì Engine được nhúng trong nó có phương thức cần thiết. Đây là cách Go tái sử dụng hành vi mà không cần kế thừa truyền thống.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống phát nhạc để minh họa cách các phương thức từ kiểu được nhúng được nâng lên kiểu bên ngoài, và cách điều này cho phép đáp ứng giao diện thông qua kết hợp.

Bạn sẽ sắp xếp code trong hai tệp:

  • audio.go: Tạo các khối cấu thành cho trình phát nhạc:
    • Một cấu trúc AudioPlayer có trường Brand (chuỗi) và phương thức Play() string trả về [Brand] playing audio
    • Một giao diện Playable yêu cầu phương thức Play() string
    • Một cấu trúc Smartphone có trường Model và nhúng AudioPlayer
    • Một cấu trúc Tablet có trường Model và nhúng AudioPlayer
  • main.go: Tạo hàm có tên StartPlayback nhận bất kỳ Playable nào và trả về kết quả của việc gọi Play(). Đọc thông tin thiết bị từ đầu vào, tạo cả một Smartphone và một Tablet, rồi minh họa rằng cả hai đều đáp ứng giao diện Playable thông qua AudioPlayer được nhúng, dù không kiểu nào tự triển khai rõ ràng Play().

Đầu vào sẽ gồm:

  • Dòng 1: Tên mẫu Smartphone
  • Dòng 2: Thương hiệu âm thanh của Smartphone
  • Dòng 3: Tên mẫu Tablet
  • Dòng 4: Thương hiệu âm thanh của Tablet

Với mỗi thiết bị, hãy in mẫu thiết bị, sau đó là kết quả khi truyền thiết bị đó vào StartPlayback.

Ví dụ, với iPhone 15, Apple Audio, iPad Pro và Beats, đầu ra của bạn sẽ là:

iPhone 15
Apple Audio playing audio
iPad Pro
Beats playing audio

Hãy chú ý rằng bạn có thể truyền cả Smartphone lẫn Tablet vào StartPlayback vì phương thức Play() từ AudioPlayer tự động được nâng lên từng kiểu bên ngoài, giúp đáp ứng giao diện Playable mà không cần thêm code.

Tự làm thử

package main

import (
	"bufio"
	"fmt"
	"os"
)

// TODO: Tạo hàm (function) StartPlayback nhận bất kỳ Playable nào
// và trả về kết quả khi gọi Play()

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// Đọc tên mẫu điện thoại thông minh
	scanner.Scan()
	smartphoneModel := scanner.Text()
	
	// Đọc tên thương hiệu âm thanh của điện thoại thông minh
	scanner.Scan()
	smartphoneBrand := scanner.Text()
	
	// Đọc tên mẫu máy tính bảng
	scanner.Scan()
	tabletModel := scanner.Text()
	
	// Đọc tên thương hiệu âm thanh của máy tính bảng
	scanner.Scan()
	tabletBrand := scanner.Text()
	
	// TODO: Tạo Smartphone có AudioPlayer được nhúng
	
	// TODO: Tạo Tablet có AudioPlayer được nhúng
	
	// TODO: In ra tên mẫu điện thoại thông minh, rồi gọi StartPlayback với điện thoại đó
	
	// TODO: In ra tên mẫu máy tính bảng, rồi gọi StartPlayback với máy tính bảng đó
	
	_ = smartphoneModel
	_ = smartphoneBrand
	_ = tabletModel
	_ = tabletBrand
	fmt.Println("TODO: Complete the implementation")
}
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: Trình biên dịch Go online