Embedding — Go’ning klassik meros (inheritance) o’rniga taklif qiladigan mexanizmi. Struct ichiga boshqa struct’ni nomsiz (faqat turi bilan) joylashtirish orqali, uning maydon va metodlari “ko’tarilgan” (promoted) holda avtomatik mavjud bo’ladi.
Embedding — struct ichiga boshqa struct’ni maydon nomisiz, faqat turi bilan qo’shish. Bu meros emas, kompozitsiya — “bu — shu” emas, “bu o’zida shuni saqlaydi” munosabati.
Embedding orqali maydon va metod ko’tarilishi
package main
import "fmt"
type Inson struct {
Ism string
}
func (i Inson) Tanishtir() {
fmt.Println("Men", i.Ism)
}
type Talaba struct {
Inson
Ball int
}
func main() {
t := Talaba{Inson: Inson{Ism: "Master Sherkulov"}, Ball: 95}
t.Tanishtir()
fmt.Println(t.Ism)
fmt.Println(t.Ball)
}
Men Master Sherkulov
Master Sherkulov
95
Inson — Talaba ichiga nomsiz joylashtirildi (Ism string kabi emas, Inson deb, faqat tur nomi bilan). Natijada Talaba Insonning Tanishtir() metodini va Ism maydonini to’g’ridan-to’g’ri, t.Inson.Ism deb yozmasdan, t.Ism shaklida meros oldi.
Bu meros emas — kompozitsiya
Muhim tushunchaviy farq: Talaba — Insonning turi emas (Talaba Insonga is-a munosabatida emas), balki Insonni o’zida saqlaydi (has-a):
package main
import "fmt"
type Inson struct {
Ism string
}
type Talaba struct {
Inson
Ball int
}
func qabulQil(i Inson) {
fmt.Println("Qabul qilindi:", i.Ism)
}
func main() {
t := Talaba{Inson: Inson{Ism: "Farrux"}, Ball: 90}
qabulQil(t.Inson)
}
Qabul qilindi: Farrux
qabulQil(i Inson) funksiyasiga tning o’zini emas, aynan t.Insonni aniq uzatish kerak bo’ldi — C++’dagi ochiq (public) merosdan farqli, Go’da Talaba avtomatik Insonning o’rnini bosa olmaydi. Bu Go dizaynerlarining ataylab qilgan tanlovi: kompozitsiya moslashuvchan, lekin chalkash “is-a” ierarxiyasini keltirib chiqarmaydi.
Metodni qayta aniqlash (override’ga o’xshash)
Talaba o’zining Tanishtir metodini yozsa, u ichma-ich Insonnikini soyalantiradi (shadow qiladi):
package main
import "fmt"
type Inson struct {
Ism string
}
func (i Inson) Tanishtir() {
fmt.Println("Men", i.Ism, "— oddiy inson")
}
type Talaba struct {
Inson
}
func (t Talaba) Tanishtir() {
fmt.Println("Men", t.Ism, "— talaba")
}
func main() {
t := Talaba{Inson: Inson{Ism: "Aziz"}}
t.Tanishtir()
t.Inson.Tanishtir()
}
Men Aziz — talaba
Men Aziz — oddiy inson
t.Tanishtir() — Talabaning o’z metodini chaqiradi (ichma-ich Insonnikini “yashiradi”). Ichki Insonning asl metodiga esa t.Inson.Tanishtir() orqali hamon murojaat qilish mumkin — hech narsa yo’qolmadi, faqat ustma-ust qo’yildi.
Bir nechta struct’ni birga embed qilish
Struct bir nechta boshqa struct’ni bir vaqtda embed qila oladi — bu Ruby’dagi mixin’larga yaqin natija beradi:
package main
import "fmt"
type Suzuvchi struct{}
func (s Suzuvchi) Suz() {
fmt.Println("Suzyapman")
}
type Yuruvchi struct{}
func (y Yuruvchi) Yur() {
fmt.Println("Yuryapman")
}
type Odam struct {
Suzuvchi
Yuruvchi
}
func main() {
o := Odam{}
o.Suz()
o.Yur()
}
Suzyapman
Yuryapman
Odam ikkita bo’sh struct’ni (Suzuvchi, Yuruvchi) embed qildi va ikkalasining metodlarini ham oldi. Bu naqsh Go’da “ko’p marotaba meros” o’rnini bosadigan, xavfsiz kompozitsiya usuli.