Interface — Go’da polimorfizmning asosi. Boshqa ko’p tillardan (Java, C++) farqli, Go’da interfeysni aniq “amalga oshiraman” deb e’lon qilish shart emas — tur interfeysdagi barcha metodlarga ega bo’lsa, u avtomatik shu interfeysni qanoatlantiradi.
Interface — bir yoki bir nechta metod imzosini o’z ichiga olgan tur. Har qanday konkret tur, agar shu metodlarni amalga oshirsa, “e’lon qilinmasdan” shu interfeysga mos keladi — bu yashirin (implicit) qanoatlantirish deb ataladi.
Interfeys e’lon qilish va yashirin qanoatlantirish
package main
import "fmt"
type Shakl interface {
Yuza() float64
}
type Tortburchak struct {
Kengligi, Balandligi float64
}
func (t Tortburchak) Yuza() float64 {
return t.Kengligi * t.Balandligi
}
type Doira struct {
Radius float64
}
func (d Doira) Yuza() float64 {
return 3.14159 * d.Radius * d.Radius
}
func chiqar(s Shakl) {
fmt.Println(s.Yuza())
}
func main() {
t := Tortburchak{Kengligi: 5, Balandligi: 3}
d := Doira{Radius: 2}
chiqar(t)
chiqar(d)
}
15
12.56636
Tortburchak va Doira — hech qayerda "men Shakl interfeysini amalga oshiraman" deb yozilmagan. Ular shunchaki Yuza() float64 metodiga ega, shu sabab ikkalasi ham avtomatik Shakl interfeysiga mos keladi. chiqar(s Shakl) funksiyasi esa aniq turni bilmasdan, faqat Yuza() metodiga tayanib ishlaydi.
Nega bu foydali — yangi tur qo’shish
Interfeysning asosiy kuchi: mavjud kodni o’zgartirmasdan, yangi tur qo’shish mumkin — u faqat kerakli metodga ega bo’lsa, darhol ishlay boshlaydi:
package main
import "fmt"
type Shakl interface {
Yuza() float64
}
type Uchburchak struct {
Asos, Balandlik float64
}
func (u Uchburchak) Yuza() float64 {
return u.Asos * u.Balandlik / 2
}
func chiqar(s Shakl) {
fmt.Println(s.Yuza())
}
func main() {
u := Uchburchak{Asos: 10, Balandlik: 4}
chiqar(u)
}
20
chiqar funksiyasi bitta ham o’zgartirilmadi — yangi Uchburchak turi Yuza() metodini olgan zahoti, avvaldan yozilgan chiqar bilan muammosiz ishladi.
Bo’sh interfeys — istalgan turni qabul qilish
interface{} (yoki zamonaviy Go’da uning taxallusi any) — hech qanday metod talab qilmaydi, shuning uchun istalgan turdagi qiymatni qabul qiladi:
package main
import "fmt"
func chiqar(qiymat any) {
fmt.Println(qiymat)
}
func main() {
chiqar(42)
chiqar("UzbekDevs")
chiqar(3.14)
chiqar(true)
}
42
UzbekDevs
3.14
true
any — interface{}ning Go 1.18’dan beri qo’shilgan qulay taxallusi. U qiymatning turi haqida hech narsa bilmaydi, shuning uchun uni ishlatishdan oldin odatda keyingi darsda ko’radigan type assertion kerak bo’ladi.
Bir nechta metodli interfeys
Interfeys bir nechta metodni talab qilishi mumkin — turi ularning barchasiga ega bo’lgandagina interfeysga mos keladi:
package main
import "fmt"
type Hisobotchi interface {
Sarlavha() string
Matn() string
}
type Buyurtma struct {
ID int
}
func (b Buyurtma) Sarlavha() string {
return fmt.Sprintf("Buyurtma #%d", b.ID)
}
func (b Buyurtma) Matn() string {
return "Holat: yetkazilmoqda"
}
func chopEt(h Hisobotchi) {
fmt.Println(h.Sarlavha())
fmt.Println(h.Matn())
}
func main() {
b := Buyurtma{ID: 501}
chopEt(b)
}
Buyurtma #501
Holat: yetkazilmoqda
Buyurtma Hisobotchi interfeysiga mos kelishi uchun ikkala metodni ham (Sarlavha va Matn) amalga oshirishi shart edi — agar faqat bittasi yozilganda, chopEt(b) chaqiruvi kompilyatsiya xatosi berardi.