Menu
CoddyTech

Kết hợp interface

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 31 trên 107.

Go cho phép bạn xây dựng các giao diện lớn hơn bằng cách kết hợp những giao diện nhỏ hơn. Thay vì định nghĩa một giao diện lớn với nhiều phương thức, bạn nhúng các giao diện hiện có vào định nghĩa giao diện mới.

type Reader interface {
    Read() string
}

type Writer interface {
    Write(data string)
}

// ReadWriter kết hợp cả hai giao diện (interface)
type ReadWriter interface {
    Reader
    Writer
}

Interface ReadWriter hiện yêu cầu cả hai phương thức Read() và Write(). Bất kỳ kiểu nào triển khai cả hai phương thức đều thỏa mãn ReadWriter, đồng thời cũng thỏa mãn riêng Reader và Writer.

type File struct {
    Name string
}

func (f File) Read() string       { return "file content" }
func (f File) Write(data string)  { fmt.Println("Writing:", data) }

func Process(rw ReadWriter) {
    content := rw.Read()
    rw.Write(content)
}

func main() {
    f := File{Name: "data.txt"}
    Process(f)  // File đáp ứng giao diện ReadWriter
}

Cách tiếp cận kết hợp này giúp giao diện gọn và tập trung. Bạn có thể kết hợp chúng tùy theo nhu cầu để tạo các hợp đồng chính xác cho hàm của mình. Thư viện chuẩn của Go sử dụng rộng rãi mẫu này, chẳng hạn như io.ReadWriter, kết hợp io.Reader và io.Writer.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống phát đa phương tiện để minh họa cách kết hợp các interface. Bạn sẽ tạo những interface nhỏ, tập trung vào một mục đích, sau đó kết hợp chúng thành một interface tổng hợp mạnh hơn mà một kiểu duy nhất có thể đáp ứng.

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

  • media.go: Định nghĩa ba interface và một struct triển khai tất cả:
    • Một interface Player có phương thức Play() string
    • Một interface Recorder có phương thức Record(content string) string
    • Một interface MediaDevice kết hợp cả Player và Recorder
    • Một struct SmartDevice có trường Name và triển khai tất cả các phương thức cần thiết
  • main.go: Tạo các hàm để minh họa cách sử dụng cùng một SmartDevice thông qua các kiểu interface khác nhau. Viết ba hàm:
    • UsePlayer nhận một Player và gọi phương thức Play của nó
    • UseRecorder nhận một Recorder và một chuỗi nội dung, sau đó gọi Record
    • UseMediaDevice nhận một MediaDevice và một chuỗi nội dung, sau đó gọi cả Record lẫn Play
    Đọc tên thiết bị và nội dung từ đầu vào, tạo một SmartDevice, rồi minh họa cách sử dụng thiết bị đó thông qua cả ba kiểu interface.

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

  • Dòng 1: Tên thiết bị
  • Dòng 2: Nội dung cần ghi

Các phương thức của bạn cần trả về chuỗi theo định dạng sau:

  • Play(): [Name] is playing
  • Record(content): [Name] recorded: [content]

Ví dụ, với MyPhone và voice memo, đầu ra sẽ là:

MyPhone is playing
MyPhone recorded: voice memo
MyPhone recorded: voice memo
MyPhone is playing

Hai dòng đầu cho biết thiết bị được sử dụng thông qua từng interface riêng lẻ (Player và Recorder). Hai dòng cuối cho biết thiết bị được sử dụng thông qua interface tổng hợp MediaDevice, vốn yêu cầu cả hai khả năng. Hãy lưu ý rằng một SmartDevice duy nhất đáp ứng cả ba interface vì nó có đủ hai phương thức cần thiết.

Tự làm thử

package main

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

// TODO: Triển khai UsePlayer nhận một Player và gọi phương thức (method) Play của nó
// Hàm này cần in ra kết quả của Play()

// TODO: Triển khai UseRecorder nhận một Recorder và một chuỗi (string) content
// Hàm này cần in ra kết quả của Record(content)

// TODO: Triển khai UseMediaDevice nhận một MediaDevice và một chuỗi content
// Hàm này cần in ra kết quả của Record(content), rồi đến Play()

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	scanner.Scan()
	deviceName := scanner.Text()
	
	scanner.Scan()
	content := scanner.Text()
	
	// TODO: Tạo một SmartDevice với tên đã cho
	
	// TODO: Sử dụng thiết bị thông qua giao diện (interface) Player
	
	// TODO: Sử dụng thiết bị thông qua giao diện Recorder
	
	// TODO: Sử dụng thiết bị thông qua giao diện MediaDevice
	
	_ = deviceName
	_ = content
	fmt.Println("Implement the solution")
}
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