Bài học theo mô-đun (1/5)
Giao diện: xác định hành vi
giao diện trong Go là một tập hợp các chữ ký phương thức. Một giá trị
thực hiện giao diện nếu nó có tất cả các phương thức đó — không
implements, không extends, không đăng ký rõ ràng. Đó là
mô hình thường được gọi là "gõ cấu trúc" hoặc "gõ vịt tĩnh":
trình biên dịch kiểm tra sự phù hợp tại thời điểm biên dịch, nhưng dựa trên
hình dạng, không phải trên tờ khai.
Khai báo một giao diện
type Greeter interface {
Greet() string
}Quy ước: tên kết thúc bằng -er cho giao diện một phương thức
(Reader, Writer, Stringer, Closer). Giao diện nhỏ
(Phương thức 1–2) là thành ngữ: thư viện chuẩn có đầy đủ
các giao diện nhỏ kết hợp với nhau (io.ReadWriter,
io.ReadCloser, …).
Thực hiện ngầm
type Person struct{ Name string }
func (p Person) Greet() string {
return "ciao " + p.Name
}
// Person satisfies Greeter because it has the required method.
var s Greeter = Person{Name: "Ada"}
fmt.Println(s.Greet())Không có từ khóa. Nếu loại có các phương thức, nó có thể được gán cho một biến của loại giao diện đó. Thế thôi.
Đa hình qua giao diện
type Robot struct{ ID string }
func (r Robot) Greet() string { return "bip " + r.ID }
func greet(s Greeter) {
fmt.Println(s.Greet())
}
greet(Person{Name: "Ada"})
greet(Robot{ID: "R2"})greet chấp nhận bất kỳ loại nào đáp ứng Greeter. Đây là con đường đi
thực hiện tính đa hình: không có thứ bậc, chỉ có khả năng.
Giao diện trống
var x interface{} = 42
var y any = "ciao" // any is the built-in alias of interface{}interface{} (hoặc any kể từ Phiên bản 1.18) không yêu cầu phương thức nào, vì vậy bất kỳ phương thức nào
giá trị thỏa mãn nó. Hữu ích cho các vùng chứa chung, nhưng để giải nén
giá trị cụ thể bạn cần xác nhận kiểu hoặc chuyển đổi kiểu
(bài học tiếp theo).
Bộ phương thức: giá trị so với bộ thu con trỏ (xem trước)
Nhớ lại Mô-đun 5:
- Các phương thức có bộ nhận giá trị nằm trong bộ phương thức của cả
Tvà*T. - Các phương thức có bộ nhận con trỏ CHỈ có trong bộ phương thức
*T.
Hậu quả thực tế:
type Counter struct{ N int }
func (c *Counter) Inc() { c.N++ }
type Incrementer interface { Inc() }
var i Incrementer = &Counter{} // OK: *Counter has Inc()
// var j Incrementer = Counter{} // ERROR: Counter (value) does NOTKhi một phương thức có bộ nhận con trỏ, bạn phải gán một con trỏ cho biến giao diện.
Hãy thử nó
Xác định một giao diện Greeter bằng một chuỗi phương thức Greet() duy nhất.
Hiển thị gợi ý
Cú pháp: `type Tên giao diện { Method(args) return }`.
Giải pháp khả dụng sau 3 lần thử
Triển khai Greeter trên loại Robot mới có chuỗi ID trường; phương thức trả về 'bip' + ID.
Hiển thị gợi ý
Không có `thực hiện`: chỉ xác định phương thức bằng chữ ký bên phải.
Giải pháp khả dụng sau 3 lần thử
Bạn khai báo loại P đó triển khai giao diện Greeter như thế nào?
type P struct{}
// ?Tóm tắt lại
- Giao diện = tập hợp các chữ ký phương thức; không
implements. - Triển khai ngầm: chỉ cần có các phương thức có chữ ký phù hợp.
- Thành ngữ: giao diện nhỏ (phương thức 1–2), tên trong
-er. interface{}/any: chấp nhận bất kỳ giá trị nào, mất an toàn về loại.- Bộ phương thức: bộ nhận con trỏ → chỉ
*Tthỏa mãn giao diện. - Go đa hình: tham số kiểu giao diện, không phân cấp.