12-bo‘lim
Metodlar
Resiverli funksiyalar, qiymat va ko'rsatkich resiveri farqi, o'z turlaringizga metod qo'shish, String metodi va joylashtirilgan metodlar.
Ushbu bo‘lim mundarijasi
Metod - bu resiveri bor funksiya. Resiver funksiya nomidan oldin, qavs ichida yoziladi.
Birinchi metod #
package main
import "fmt"
type Talaba struct {
Ism string
Ball int
}
func (t Talaba) Otdimi() bool {
return t.Ball >= 60
}
func (t Talaba) Tavsif() string {
return fmt.Sprintf("%s: %d ball", t.Ism, t.Ball)
}
func main() {
a := Talaba{Ism: "Malika", Ball: 88}
b := Talaba{Ism: "Aziza", Ball: 45}
fmt.Println(a.Tavsif(), a.Otdimi())
fmt.Println(b.Tavsif(), b.Otdimi())
}
Malika: 88 ball true
Aziza: 45 ball false
func (t Talaba) Otdimi() bool - Talaba turiga tegishli metod.
t - resiver, ya'ni metod chaqirilgan qiymat.
Resiverga istalgan nom berish mumkin, lekin Go da odatda turning
bosh harfi ishlatiladi: t, s, m.
Java va Python da metod ichida this yoki self avtomatik paydo
bo'ladi. Go da esa resiver ochiq e'lon qilinadi.
Bu ko'proq yozuv, lekin hech qanday sehr yo'q: metod - oddiy funksiya, uning birinchi argumenti shunchaki boshqa joyda yozilgan.
Qiymat va ko'rsatkich resiveri #
package main
import "fmt"
type Hisoblagich struct {
Soni int
}
func (h Hisoblagich) OshirNusxa() {
h.Soni++
}
func (h *Hisoblagich) Oshir() {
h.Soni++
}
func main() {
x := Hisoblagich{}
x.OshirNusxa()
x.OshirNusxa()
fmt.Println("nusxa resiveri:", x.Soni)
x.Oshir()
x.Oshir()
fmt.Println("ko'rsatkich resiveri:", x.Soni)
}
nusxa resiveri: 0
ko'rsatkich resiveri: 2
Bu 8-bo'limdagi qoidaning aynan o'zi: qiymat resiveri nusxa oladi, shuning uchun o'zgarish yo'qoladi.
O'zgartiradigan har bir metod ko'rsatkich resiveriga ega bo'lishi kerak.
E'tibor bering: x.Oshir() deb yozildi, (&x).Oshir() emas -
garchi metod *Hisoblagich ni kutsa ham.
Go buni o'zi hal qiladi: agar o'zgaruvchi manzil olinadigan
bo'lsa, kompilyator & ni avtomatik qo'yadi. Teskarisi ham
to'g'ri - ko'rsatkichda qiymat resiverli metodni chaqirsangiz, Go
* ni o'zi qo'yadi.
Shuning uchun kundalik kodda farqni deyarli sezmaysiz. Lekin u interfeyslar bilan ishlaganda muhim bo'ladi - keyingi bo'limda.
Qaysi birini tanlash #
| Holat | Resiver |
|---|---|
| Metod qiymatni o'zgartiradi | Ko'rsatkich |
| Struktura katta | Ko'rsatkich |
| Turda boshqa ko'rsatkich metodlari bor | Ko'rsatkich |
| Kichik, o'zgarmas tur | Qiymat |
Agar turda kamida bitta ko'rsatkich resiverli metod bo'lsa, hammasini ko'rsatkich resiverli qiling.
Aralash holat chalkashlik tug'diradi: o'quvchi har bir metod uchun alohida o'ylab ko'rishi kerak bo'ladi, kompilyator esa ba'zi interfeys tekshiruvlarida kutilmaganda xato beradi.
Bu Go jamoasining rasmiy tavsiyasi.
Struktura bo'lmagan turlarga ham #
package main
import "fmt"
type Harorat float64
func (h Harorat) Farengeyt() float64 {
return float64(h)*1.8 + 32
}
func (h Harorat) Tavsif() string {
switch {
case h < 0:
return "sovuq"
case h < 20:
return "salqin"
case h < 30:
return "iliq"
default:
return "issiq"
}
}
func main() {
bugun := Harorat(27.5)
fmt.Println(bugun.Farengeyt())
fmt.Println(bugun.Tavsif())
fmt.Println(Harorat(-5).Tavsif())
}
81.5
iliq
sovuq
Metod faqat strukturalarga emas, har qanday nomlangan turga qo'shilishi mumkin.
type Harorat float64 - bu float64 ning yangi nomi emas, balki
yangi tur. Unga o'z metodlaringizni bog'lash mumkin.
float64(h)*1.8 qatoriga e'tibor bering. Harorat va float64 -
turli turlar, shuning uchun 3-bo'limdagi qoida ishlaydi: aniq
o'tkazish kerak.
Bu qulaysizlikdek tuyuladi, lekin foydasi bor: Harorat ni
tasodifan Masofa yoki oddiy songa qo'shib yuborolmaysiz.
Kompilyator bunga yo'l qo'ymaydi.
iota va metod birga #
package main
import "fmt"
type Holat int
const (
Yangi Holat = iota
Jarayonda
Bajarilgan
)
func (h Holat) String() string {
switch h {
case Yangi:
return "yangi"
case Jarayonda:
return "jarayonda"
case Bajarilgan:
return "bajarilgan"
default:
return "noma'lum"
}
}
func main() {
h := Jarayonda
fmt.Println(h)
fmt.Printf("%v / %d\n", h, int(h))
fmt.Println(Holat(99))
}
jarayonda
jarayonda / 1
noma'lum
Mana 3-bo'limda va'da qilingan narsa: iota bilan yaratilgan
doimiylar endi o'z turiga va o'z nomiga ega.
String metodi maxsus #
package main
import "fmt"
type Pul struct {
Tiyin int
}
func (p Pul) String() string {
return fmt.Sprintf("%d.%02d so'm", p.Tiyin/100, p.Tiyin%100)
}
func main() {
narx := Pul{Tiyin: 1250075}
fmt.Println(narx)
fmt.Printf("%v\n", narx)
fmt.Println("Narxi:", narx)
royxat := []Pul{{Tiyin: 500}, {Tiyin: 125}}
fmt.Println(royxat)
}
12500.75 so'm
12500.75 so'm
Narxi: 12500.75 so'm
[5.00 so'm 1.25 so'm]
String() string metodini yozsangiz, fmt paketi uni
avtomatik ishlatadi - Println, Printf("%v"), hatto slice
ichida ham.
Bu Go da interfeysning birinchi amaliy misoli. Keyingi bo'limda uning qanday ishlashini ko'ramiz.
Bu juda oson tushib qoladigan tuzoq:
func (p Pul) String() string {
return fmt.Sprintf("%v", p) // cheksiz rekursiya
}
%v String() ni chaqiradi, u yana %v ni... Dastur to'xtaguncha
davom etadi va stack overflow bilan qulaydi.
Yechim: ichkarida turni o'zgartirib yuboring:
func (p Pul) String() string {
return fmt.Sprintf("%d tiyin", p.Tiyin) // maydon, p emas
}
Joylashtirilgan metodlar #
package main
import "fmt"
type Shaxs struct {
Ism string
}
func (s Shaxs) Salomlash() string {
return "Salom, men " + s.Ism
}
type Talaba struct {
Shaxs
Guruh string
}
func main() {
t := Talaba{
Shaxs: Shaxs{Ism: "Husanboy"},
Guruh: "A-1",
}
fmt.Println(t.Salomlash())
fmt.Println(t.Ism, t.Guruh)
}
Salom, men Husanboy
Husanboy A-1
Talaba da Salomlash metodi yozilmagan, lekin u ishlaydi.
Joylashtirilgan Shaxs turining metodlari Talaba ga ham
o'tadi - 11-bo'limdagi maydonlar kabi.
Metodni ustidan yozish #
package main
import "fmt"
type Shaxs struct {
Ism string
}
func (s Shaxs) Salomlash() string {
return "Salom, men " + s.Ism
}
type Oqituvchi struct {
Shaxs
Fan string
}
func (o Oqituvchi) Salomlash() string {
return o.Shaxs.Salomlash() + ", " + o.Fan + " o'qituvchisiman"
}
func main() {
o := Oqituvchi{
Shaxs: Shaxs{Ism: "Dilnoza"},
Fan: "matematika",
}
fmt.Println(o.Salomlash())
fmt.Println(o.Shaxs.Salomlash())
}
Salom, men Dilnoza, matematika o'qituvchisiman
Salom, men Dilnoza
Tashqi turda bir xil nomli metod yozsangiz, u ustunlik qiladi.
Ichkisiga baribir murojaat qilish mumkin: o.Shaxs.Salomlash().
Natija vorislikka o'xshaydi, lekin mexanizm boshqacha.
Vorislikda Oqituvchi bu Shaxs bo'lardi va uni Shaxs
kutilgan har qanday joyga berish mumkin edi.
Go da esa Oqituvchi shunchaki ichida Shaxs saqlaydi.
Kompilyator metod chaqiruvini avtomatik ravishda ichkariga
yo'naltiradi, xolos.
Turlarni almashtirib ishlatish kerak bo'lsa, interfeys ishlatiladi - keyingi bo'limda.
Metod - oddiy qiymat #
package main
import "fmt"
type Talaba struct {
Ism string
}
func (t Talaba) Salomlash() string {
return "Salom, " + t.Ism
}
func main() {
t := Talaba{Ism: "Nodira"}
f := t.Salomlash
fmt.Println(f())
g := Talaba.Salomlash
fmt.Println(g(Talaba{Ism: "Kamola"}))
}
Salom, Nodira
Salom, Kamola
t.Salomlash - qavssiz yozilsa, u funksiya qiymati bo'ladi va
t ni ichida saqlab qoladi.
Talaba.Salomlash esa resiverni birinchi argument sifatida
qabul qiladigan oddiy funksiya. Bu metodlarning aslida nima ekanini
ko'rsatadi.
- Strukturaga ikkita qiymat resiverli metod yozing.
- Ko'rsatkich resiveri bilan maydonni o'zgartiring.
- Qiymat resiveri o'zgartira olmasligini isbotlang.
type Harorat float64yaratib, unga metod qo'shing.iotadoimiylarigaStringmetodini yozing.StringmetodiPrintlnda avtomatik ishlashini ko'ring.- Joylashtirish orqali metodni meros qilib oling.
- Tashqi turda bir xil nomli metod yozib, ustunligini ko'ring.
- Ichki metodga ochiq murojaat qiling.
- Metodni o'zgaruvchiga berib, keyin chaqiring.
Xulosa #
- Metod - resiveri bor funksiya; resiver nomdan oldin, qavs ichida yoziladi.
- Go da
thisyokiselfyo'q - resiver ochiq e'lon qilinadi. - Qiymat resiveri nusxa oladi; o'zgartiradigan metod ko'rsatkich resiveri bilan yoziladi.
- Bir turdagi metodlarning resiverlarini aralashtirmang.
- Metodni har qanday nomlangan turga qo'shish mumkin, faqat strukturaga emas.
String() stringmetodi maxsus:fmtuni avtomatik ishlatadi - lekin ichida%vyozmang.- Joylashtirilgan turning metodlari tashqariga o'tadi; bir xil nomli metod esa ularni ustidan yozadi.
- Metod - oddiy qiymat: uni o'zgaruvchiga berish mumkin.
Keyingi bo'limda interfeyslarni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.