Sinflar va obyektlar mavzusini davom ettirib, obyektning ichki holatiga tashqaridan qanday xavfsiz kirish va o’zgartirish mumkinligini ko’ramiz. Ruby’da C++ yoki Python’dan farqli, instans o’zgaruvchisiga (@ism) sinf tashqarisidan hech qachon to’g’ridan-to’g’ri kirib bo’lmaydi — buning uchun har doim metod kerak.
Instans metodi — sinf ichida e’lon qilingan, faqat shu sinfdan yaratilgan obyekt orqali chaqiriladigan metod. Obyektning
@bilan boshlangan o’zgaruvchilariga faqat shunday metodlar orqali kirish mumkin.
Qo’lda yozilgan getter va setter
Instans o’zgaruvchisini o’qish va yozish uchun odatiy Ruby metodlari yozamiz. Diqqat: setter metod nomi = bilan tugaydi — bu maxsus sintaksisga ruxsat beradi:
class Foydalanuvchi
def ism=(qiymat)
@ism = qiymat
end
def ism
@ism
end
end
a = Foydalanuvchi.new
b = Foydalanuvchi.new
a.ism = "Farrux"
b.ism = "Master Sherkulov"
puts a.ism
puts b.ism
Farrux
Master Sherkulov
def ism=(qiymat) — nomi = bilan tugagani uchun Ruby a.ism = "Farrux" yozuvini a.ism=("Farrux") chaqiruviga avtomatik aylantiradi — bu oddiy o’zgaruvchiga qiymat berish kabi tabiiy ko’rinadi, aslida esa metod chaqiruvi. def ism esa qiymatni o’qib qaytaradi.
Instans o’zgaruvchisiga to’g’ridan-to’g’ri kirish imkonsizligi
Getter metodi yozilmagan bo’lsa, tashqaridan @ o’zgaruvchisiga hech qanday yo’l bilan kira olmaysiz:
class Mahsulot
def narx=(qiymat)
@narx = qiymat
end
end
m = Mahsulot.new
m.narx = 50000
begin
puts m.narx
rescue NoMethodError => xato
puts "Xato turi: #{xato.class}"
end
Xato turi: NoMethodError
Setter yozilgan, lekin getter yozilmagan — shuning uchun m.narx chaqiruvi xato beradi: bunday metod umuman mavjud emas. Bu — Ruby’da enkapsulatsiya nima uchun “standart holat” deb atalishining sababi: siz ochib bermaguningizcha, hech narsa tashqariga ko’rinmaydi. (begin...rescue — xatoni ushlash usuli, uni keyinroq alohida darsda chuqur ko’ramiz.)
self — joriy obyektga ishora
Sinf ichida self joriy obyektning o’zini bildiradi. U, ayniqsa, obyekt ichidan o’zining boshqa metodini chaqirishda ishlatiladi:
class Hisob
def balans=(qiymat)
@balans = qiymat
end
def balans
@balans
end
def ikkilantir
self.balans = balans * 2
end
end
h = Hisob.new
h.balans = 100
h.ikkilantir
puts h.balans
200
self.balans = ... — setterni aniq chaqirish uchun self zarur (balans = ... yozilsa, Ruby buni yangi lokal o’zgaruvchi deb tushunган bo’lardi, setter emas). O’ng tomondagi balans esa — getter chaqiruvi, bu yerda self yozish shart emas.
Bir nechta instans o’zgaruvchisi
Real obyektlar odatda bir nechta holatni birga saqlaydi:
class Kitob
def sozla(nomi, sahifa)
@nomi = nomi
@sahifa = sahifa
end
def malumot
"#{@nomi} — #{@sahifa} bet"
end
end
k = Kitob.new
k.sozla("Ruby asoslari", 240)
puts k.malumot
Ruby asoslari — 240 bet
sozla metodi ikkita instans o’zgaruvchisini birdaniga o’rnatdi. Ammo obyektni ikki bosqichda (.new, keyin .sozla) tayyorlash noqulay — keyingi darsda buni bir qadamga tushiradigan konstruktorni ko’ramiz.