Tôi muốn mở rộng câu trả lời được đưa ra bởi @jimt ở đây . Câu trả lời đó là chính xác và giúp tôi rất nhiều trong việc phân loại này. Tuy nhiên, có một số cảnh báo cho cả hai phương thức (bí danh, nhúng) mà tôi gặp rắc rối.
lưu ý : Tôi sử dụng thuật ngữ cha mẹ và con cái, mặc dù tôi không chắc đó là cách tốt nhất để sáng tác. Về cơ bản, cha mẹ là loại mà bạn muốn sửa đổi cục bộ. Trẻ em là loại mới cố gắng thực hiện sửa đổi đó.
Phương pháp 1 - Định nghĩa kiểu
type child parent
// or
type MyThing imported.Thing
- Cung cấp quyền truy cập vào các lĩnh vực.
- Không cung cấp quyền truy cập vào các phương thức.
type child struct {
parent
}
// or with import and pointer
type MyThing struct {
*imported.Thing
}
- Cung cấp quyền truy cập vào các lĩnh vực.
- Cung cấp quyền truy cập vào các phương pháp.
- Yêu cầu xem xét để khởi tạo.
Tóm lược
- Sử dụng phương thức thành phần, cha mẹ nhúng sẽ không khởi tạo nếu nó là một con trỏ. Cha mẹ phải được khởi tạo riêng.
- Nếu cha mẹ được nhúng là một con trỏ và không được khởi tạo khi con được khởi tạo, sẽ xảy ra lỗi vô hiệu hóa con trỏ con trỏ.
- Cả hai định nghĩa kiểu và trường hợp nhúng cung cấp quyền truy cập vào các trường của cha mẹ.
- Định nghĩa kiểu không cho phép truy cập vào các phương thức của cha mẹ, nhưng nhúng cha mẹ thì không.
Bạn có thể thấy điều này trong đoạn mã sau.
ví dụ làm việc trên sân chơi
package main
import (
"fmt"
)
type parent struct {
attr string
}
type childAlias parent
type childObjParent struct {
parent
}
type childPointerParent struct {
*parent
}
func (p *parent) parentDo(s string) { fmt.Println(s) }
func (c *childAlias) childAliasDo(s string) { fmt.Println(s) }
func (c *childObjParent) childObjParentDo(s string) { fmt.Println(s) }
func (c *childPointerParent) childPointerParentDo(s string) { fmt.Println(s) }
func main() {
p := &parent{"pAttr"}
c1 := &childAlias{"cAliasAttr"}
c2 := &childObjParent{}
// When the parent is a pointer it must be initialized.
// Otherwise, we get a nil pointer error when trying to set the attr.
c3 := &childPointerParent{}
c4 := &childPointerParent{&parent{}}
c2.attr = "cObjParentAttr"
// c3.attr = "cPointerParentAttr" // NOGO nil pointer dereference
c4.attr = "cPointerParentAttr"
// CAN do because we inherit parent's fields
fmt.Println(p.attr)
fmt.Println(c1.attr)
fmt.Println(c2.attr)
fmt.Println(c4.attr)
p.parentDo("called parentDo on parent")
c1.childAliasDo("called childAliasDo on ChildAlias")
c2.childObjParentDo("called childObjParentDo on ChildObjParent")
c3.childPointerParentDo("called childPointerParentDo on ChildPointerParent")
c4.childPointerParentDo("called childPointerParentDo on ChildPointerParent")
// CANNOT do because we don't inherit parent's methods
// c1.parentDo("called parentDo on childAlias") // NOGO c1.parentDo undefined
// CAN do because we inherit the parent's methods
c2.parentDo("called parentDo on childObjParent")
c3.parentDo("called parentDo on childPointerParent")
c4.parentDo("called parentDo on childPointerParent")
}
“extension methods are not object-oriented”
) cho C #, nhưng khi nhìn vào chúng ngày hôm nay, tôi đã nhớ ngay đến các giao diện của Go (và cách tiếp cận của nó để suy nghĩ lại về hướng đối tượng), và sau đó tôi đã có câu hỏi này.