Open mtchuyen opened 2 years ago
https://viblo.asia/p/lap-trinh-huong-doi-tuong-voi-go-07LKXA7kZV4
https://techmaster.vn/posts/34913/go-co-phai-la-1-ngon-ngu-lap-trinh-huong-doi-tuong
https://kungfutech.edu.vn/bai-viet/go/composition-trong-go
https://golangbot.com/inheritance/
https://www.tutorialspoint.com/composition-in-golang
Composition:
Go is not an OOP language, it doesn't have inheritance, but can use Composition instead.
Sử dụng Composition có thể giúp chúng ta:
Giả sử ta định nghĩa 1 type có tên là Context
, và nó có 1 method là Get
type Context struct {
kv map[string]string
}
func (c *Context) Get(k string) string {
return c.kv[k]
}
Giờ ta sẽ định nghĩa 1 type mới có tên là BusinessContext
type BusinessContext struct {
Context
}
Ta gọi Context
là embed typed của BusinessContext
Giờ ta sẽ làm cụ thể 2 vấn đề Reusability & Reduce
, vẫn với 2 type đã định nghĩa ở trên
ctx := &Context{kv:map[string]string{"name":"Pallat"}}
bctx := &BusinessContext{ctx}
println(bctx.Get("name"))
như vậy type BusinessContext
đã re-used lại method .Get
của type Context
, và không cần phải viết lại code (reduce)
Ở ví dụ trên, có nhược điểm là nếu cấp API ra ngoài, thì người dùng không thể biết được trong type Context
có key/value
= name/<<ex:Pallat>>
.
Vậy nên type BusinessContext
viết thêm 1 method giúp người dùng thuận tiện hơn
func (c *BusinessContext) Name() string {
return c.Context.Get("name")
}
như vậy 2 dòng code dưới đây là tương đương nhau
println(bctx.Get("name"))
println(bctx.Name())
nhờ tính năng Composition
của Go, nên việc mở rộng method trong việc "kế thừa" (thực tế là re-used) dễ dàng hơn.
Ở ví dụ trên, bctx.Get("name")
sẽ gọi tới method .Get
của type Context
. Lúc này có thể hiểu type BusinessContext
cũng có 1 method .Get
(nhưng thực ra là của Context
)
Function .Get
(của lời gọi bctx.Get("name")
) có thể được mở rộng hơn (Extensibility
) bằng cách định nghĩa một method mới cho type BusinessContext
:
func (c *BusinessContext) Get(k string) string {
return c.Context.Get(k) + "was calling (được gọi tới)"
}
Và vẫn dùng bình thường: bctx.Get("name")
. Đó là sự Override
http://jim-mcbeath.blogspot.com/2019/11/go-composition-vs-inheritance.html
https://www.digitalocean.com/community/tutorials/composition-vs-inheritance
https://viblo.asia/p/tim-hieu-ve-nguyen-ly-composition-over-inheritance-YWOZr0or5Q0 https://daynhauhoc.com/t/tim-hieu-ve-nguyen-ly-composition-over-inheritance/42665
https://en.wikipedia.org/wiki/Composition_over_inheritance
https://odetocode.com/blogs/scott/archive/2019/01/03/composition-over-inheritance-in-go.aspx
https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance
Composition và Inheritance là 2 kĩ thuật trong các kĩ thuật để tránh vấn đề Duplication bằng cách reuse từ class khác, thay đổi 1 số thành phần. Inheritance thực thi tại compile time, có thể nhìn thấy cơ chế reuse của nó. Ngược lại, composition thực thi ở runtime, khó nhìn thấy cách reuse. Đối với app nhỏ thì composition hay inheritance không có sự khác biệt, đọc code là hiểu ngay, nhưng khi app phát triển, thì lập trình viên khó hiểu cách reuse ở composition hơn là ở inheritance. Quy trình phát triển phần mềm hiện tại là quy trình Agile, app phải đáp ứng được yêu cầu thay đổi (change) nên người ta chuộng composition hơn nheritance. Vì họ có thể thay đổi cơ chế kế thừa tại runtime mà không cần tác động source code, chỉ cần tạo file mới. Trong khi đối với inheritance, phải compile lại nguyên toàn bộ class hierarchy, và khi change requirement xảy ra ở superclass thì tất cả subclasses đều bị ảnh hưởng.
cái này hôm trước có đọc 1 cái ví dụ trong cuốn HeadFirstDesignPatterns nó giải thích rất rõ ràng về vấn đề này tùy vào từng trường hợp mà áp dụng cho hợp lý làm sao đảm bảo được sự linh hoạt của chương trình , chứ không phải cứ dùng composition là tốt đâu mấy cái này liên quan đế thiết kế hướng đối tượng …trên youtube cũng có vài video nói về cái này mà mình thấy ông nào cũng đưa vd đúng của mình ra để cãi cả nên…:grin:
Hầu hết ngôn ngữ lập trình ra đời gần đây toàn loại bỏ tính năng inheritance. Golang là 1 ví dụ, Go chỉ sử dụng composition thôi. Mới đây thì Apple giới thiệu ngôn ngữ Swift, trong Swift đưa ra khái niệm mới là Value Type, cũng không có inheritance.
an object is some data (a block of memory) with attached logic (behavior) that can access that data.
// this is a type alias that gives a name to a specific data structure
type StringTable struct {
values [][]string
}
// outside of the type declaration, attached to an existing type
func (s StringTable) NoOp() { }
// define a readable CSV representation for the StringTable
func (s StringTable) String() string {
lines := make([]string, 0)
for _, row := range s.values {
lines = append(lines, strings.Join(row, ","))
}
return strings.Join(lines, "\n")
}
Encapsulation: This pillar is all about controlling access to the enclosed (encapsulated) data in an object.
Traditionally, languages use private and public (and sometimes protected
) field modifiers to set access and visibility.
In Go access and visibility works on a package level and follows a convention of UPPERCASE names
for public (visible outside of the current package) and lowercase
for private (visible within the package).
This is where it gets tricker with Go.
Polymorphism in Go feels a little different as well.
Instead of polymorphism through inheritance, Go have **interfaces: Various types can implement an interface
OO in Go
https://grigsby.dev/oo-in-go-go-d49d8e73255a
Inheritance-in-Go
https://alenalex.medium.com/inheritance-in-go-82212be68576
Object-oriented Programming in Go
https://medium.com/@mmisyaath/object-oriented-programming-in-go-199de8efae15
Keywords: