Goda "meros" (inheritance) yo'q — buning o'rniga nima bor?
Java yoki Python kabi tillarda class'lar bir-biridan meros olishi (inheritance) orqali umumiy xatti-harakatni bo'lishadi. Goda klassik meros olish tushunchasi umuman yo'q — buning o'rniga Go kompozitsiya (composition) falsafasiga tayanadi: kichik, mustaqil bo'laklarni bir-biriga "joylashtirib" (embedding), yangi, kengroq imkoniyatli tur yasaladi.
Bu dars — struct (19-dars) va interface (30-dars) darslarining bevosita davomi bo'lib, ularga tegishli, ammo ilgari ko'rilmagan embedding mexanizmini chuqur yoritadi.
package main
import "fmt"
type Animal struct {
Name string
}
func (a Animal) Eat() {
fmt.Println(a.Name, "ovqatlanmoqda")
}
// Dog o'z ichiga Animal'ni "joylashtirib" (embed qilib) oladi
type Dog struct {
Animal // e'tibor bering: maydon nomi yo'q, faqat tur nomi!
Breed string
}
func main() {
d := Dog{
Animal: Animal{Name: "Rex"},
Breed: "Ovcharka",
}
// Dog'ning o'zida Name maydoni yo'q, lekin Animal'dan "meros" bo'lgandek ishlatiladi
fmt.Println(d.Name)
// Xuddi shunday, Animal'ning Eat() metodi ham Dog orqali to'g'ridan-to'g'ri chaqiriladi
d.Eat()
// to'liq yo'l bilan ham murojaat qilish mumkin
fmt.Println(d.Animal.Name)
}
Natija:
Rex
Rex ovqatlanmoqda
Rex
[!IMPORTANT]
Animal Animaldeb emas, faqatAnimaldeb yozilganiga e'tibor bering — maydon nomi ko'rsatilmagan, faqat tur nomi yozilgan. Aynan shu — embeddingni oddiy "struct ichida struct" (masalan,Engine Enginekabi nomlangan maydon)dan farqlaydi: embedding qilinganda, ichki turning barcha ochiq (eksport qilingan) maydonlari va metodlari tashqi turga avtomatik "ko'chib o'tadi" (bu — promotion, ko'tarilish deyiladi).
Agar tashqi tur ichki tur bilan bir xil nomdagi metodni o'zi ham belgilasa, tashqi turning o'z metodi ustunlik qiladi:
package main
import "fmt"
type Base struct{}
func (b Base) Greet() string {
return "Salom, Base"
}
type Derived struct {
Base
}
// Derived o'zining Greet() metodini belgilaydi
func (d Derived) Greet() string {
return "Salom, Derived (o'zining metodi)"
}
func main() {
d := Derived{}
fmt.Println(d.Greet()) // Derived'ning o'z metodi ishlaydi
fmt.Println(d.Base.Greet()) // Base'nikini ham alohida chaqirish mumkin
}
Natija:
Salom, Derived (o'zining metodi)
Salom, Base
[!NOTE] Bu klassik ob'ektga yo'naltirilgan tillardagi "override" (qayta belgilash)ga juda o'xshaydi, lekin texnik jihatdan farq bor: bu yerda polimorfizm yo'q — Go kompilyatsiya vaqtida qaysi
Greet()chaqirilishini aniq biladi (bu — statik bog'lanish), boshqa tillardagi kabi dinamik (runtime'da aniqlanadigan) emas.
Xuddi struct kabi, interfeyslar ham bir-biriga joylashtirilishi mumkin — bu kichik interfeyslardan kattaroq interfeys yasash imkonini beradi:
package main
import "fmt"
type Reader interface {
Read() string
}
type Writer interface {
Write(string)
}
// ReadWriter — Reader va Writer'ning barcha metodlarini birlashtiradi
type ReadWriter interface {
Reader
Writer
}
type File struct {
content string
}
func (f *File) Read() string {
return f.content
}
func (f *File) Write(s string) {
f.content = s
}
func main() {
var rw ReadWriter = &File{}
rw.Write("Salom")
fmt.Println(rw.Read())
}
Natija:
Salom
*File turi Read() va Write() metodlarining ikkalasini ham amalga oshirgani uchun, u avtomatik ravishda ReadWriter interfeysini ham qanoatlantiradi — buni alohida e'lon qilishning hojati yo'q (interfeyslar implicit — "yashirin" tarzda amalga oshiriladi, buni Interfeys darsida ko'rgan edik).
[!NOTE] Standart kutubxonadagi
io.ReadWriteraynan shu pattern bo'yicha,io.Readervaio.Writerni birlashtirib yasalgan (iodarsida ko'rgan edik).
| Meros olish (boshqa tillarda) | Kompozitsiya / Embedding (Goda) |
|---|---|
Qattiq, ierarxik bog'liqlik (Dog extends Animal) | Erkin, moslashuvchan birlashtirish |
| Bir nechta ota-class'dan meros olish ko'pincha muammoli | Bir nechta turni bemalol birga joylashtirish mumkin |
| Chuqur ierarxiyalar tushunishni qiyinlashtiradi | Har bir bo'lak mustaqil va alohida tushunarli |
// Goda bir nechta turni bemalol birga joylashtirish mumkin — muammosiz:
type Robot struct {
Animal // harakat va ovqatlanish xatti-harakati (masalan)
Engine // dvigatel xususiyatlari
Metadata // umumiy ma'lumotlar
}
| Tushuncha | Ma'nosi |
|---|---|
| Struct embedding | Bir struct'ni ikkinchisi ichiga (nomsiz) joylashtirish |
| Promotion (ko'tarilish) | Ichki turning maydon/metodlari tashqi tur orqali to'g'ridan-to'g'ri ishlatilishi |
| Metodni qayta belgilash | Tashqi tur ichki turdagi bilan bir xil nomli metod yozsa, o'ziniki ustunlik qiladi |
| Interface embedding | Kichik interfeyslarni birlashtirib, kattaroq interfeys yasash |
[!IMPORTANT] Embedding — Goning "kichik interfeyslar va aniq tuzilmalar yordamida katta narsalarni qurish" falsafasining markazida turadi. Standart kutubxonaning ko'p qismi (
io.ReadWriter,http.Handlerva h.k.) aynan shu prinsipga asoslangan.