Private maydonlar — # belgisi
Muammodan boshlaylik
Bank hisobini ifodalovchi class yozdingiz. Balansni o'zgartirish uchun yechish metodi bor — u ichida tekshiruv qiladi.
Lekin muammo bor:
const hisob = new BankHisobi("Jasur", 1_000_000);
hisob.yechish(200_000); // ← to'g'ri yo'l, tekshiruv bor
hisob.balans = 999_999_999; // ← bu ham ishlaydi. Hech narsa to'sqinlik qilmayapti.
balans — tashqaridan bevosita o'zgartirilmasligi kerak. Faqat yechish va qo'shish metodlari orqali. Lekin oddiy this.balans = ... bilan e'lon qilingan xususiyatni hech kim to'xtatib qo'ya olmaydi.
Bu — enkapsulatsiya muammosi. Ichki holat (state) tashqaridan yashirilishi kerak.
Enkapsulatsiya nima?
Enkapsulatsiya — ob'ektning ichki ishlarini yashirish. Foydalanuvchiga faqat ruxsat etilgan narsalar ko'rinadi; qanday ishlashi — ichki sir.
Hayotiy o'xshatma
Avtomat kassa mashinasi (ATM). Siz ekranda tugmalarni bosasiz: "500 000 so'm yeching". ATM ichida nima bo'ladi — bilmaysiz va bilishingiz shart emas. Bank ma'lumotlar bazasi, shifrlash, balans tekshiruvi — hammasi ichki. Siz faqat "yechish" tugmasiga borasiz, u sizga ruxsat berilgan operatsiyani bajaradi. Ichki hisoblagichni to'g'ridan o'zingiz o'zgartirishning imkoni yo'q.
# belgisi — o'sha "ichki xona". Tashqaridan kirish mumkin emas.
# belgisi qanday ishlaydi?
# bilan boshlanuvchi xususiyat — faqat class ichidan ko'rinadi. Tashqaridan, hatto bola classdan ham ko'rinmaydi.
class BankHisobi {
#balans; // ← bu xususiyat class tashqarisida mavjud emas
constructor(egasi, boshlangich) {
this.egasi = egasi; // ← oddiy, tashqaridan ko'rinadi
this.#balans = boshlangich; // ← private, faqat ichkaridan
}
yechish(miqdor) {
if (miqdor > this.#balans) {
throw new Error("Mablag' yetarli emas");
}
this.#balans -= miqdor; // ← class ichidan murojaat mumkin ✅
}
get balans() {
return this.#balans; // ← faqat o'qish imkonini beradi
}
}
const hisob = new BankHisobi("Jasur", 1_000_000);
hisob.yechish(200_000);
console.log(hisob.balans); // 800_000 ✅ — getter orqali o'qildi
hisob.#balans = 999_999; // ❌ SyntaxError — class tashqarisida ko'rinmaydi
hisob.balans = 999_999; // ❌ setter yo'q — o'zgartirib bo'lmaydi
Nima uchun bu muhim?
Oldingi holatda: hisob.balans = 999_999_999 — ishlardi. Tekshiruv chetlab o'tilar edi.
Endi: balansni o'zgartirish uchun faqat yechish yoki qo'shish orqali o'tish kerak. U yerda barcha tekshiruvlar bor. Boshqa yo'l yo'q.
Private metodlar
Metodlar ham private bo'lishi mumkin. Faqat class ichida chaqiriladigan yordamchi metodlar uchun.
Hayotiy o'xshatma
Bankomat ekranda siz ko'radigan tugmalar — oddiy metodlar. Lekin ATM ichida "kartani tekshirish", "bankka ulanish", "operatsiya jurnalini yozish" degan jarayonlar bor — siz bularni ko'rmaysiz, to'g'ridan chaqira olmaysiz. Bular — private metodlar.
class ToLov {
#kartaRaqami;
constructor(raqam) {
this.#kartaRaqami = raqam;
}
// Foydalanuvchi ko'radigan yagona narsa:
info() {
if (!this.#formatToGrimi()) {
throw new Error("Karta raqami noto'g'ri");
}
return this.#yashir(); // ← tashqariga faqat yashirilgan ko'rinish
}
// Ichki yordamchi metodlar — tashqaridan ko'rinmaydi:
#formatToGrimi() {
return this.#kartaRaqami.length === 16;
}
#yashir() {
return "*".repeat(12) + this.#kartaRaqami.slice(-4);
}
}
const karta = new ToLov("1234567890123456");
console.log(karta.info()); // "************3456" ✅
karta.#formatToGrimi(); // ❌ SyntaxError
_ bilan # ning farqi
Bir vaqtlar dasturchilar xususiyat nomi oldiga _ qo'yib "bu private" degan signal berar edi:
class Eski {
constructor() {
this._ichki = "meni o'zgartirma!";
}
}
const ob = new Eski();
ob._ichki = "o'zgartirdim :)"; // ✅ ishlaydi — JavaScript to'xtatmaydi
_ — faqat dasturchi uchun ogohlantirish. JavaScript e'tibor bermaydi. Agar boshqa dasturchi qoidani bilmasa yoki e'tibor bermasa — to'g'ridan o'zgartiradi.
# — tilning o'zi taqiqlaydi. Xohlasang ham o'zgartira olmaysan.
Tez-tez uchraydigan xatolar
Private maydonni oldindan e'lon qilmaslik:
Private maydonlar class tanasida — constructordan tashqarida e'lon qilinishi shart. E'lonsiz foydalanish — sintaksis xatosi.
class Xato {
constructor() {
this.#qiymat = 42; // ❌ SyntaxError: Private field '#qiymat' must be declared
}
}
class ToGri {
#qiymat; // ✅ avval e'lon
constructor() {
this.#qiymat = 42;
}
}
Bola classdan ota classning private maydoniga murojaat:
Private maydon — faqat u e'lon qilingan classda ko'rinadi. Hatto extends bilan meros olgan bola class ham ko'ra olmaydi.
class Ota {
#sir = "maxfiy";
}
class Bola extends Ota {
ochib_ber() {
return this.#sir; // ❌ SyntaxError — Bola classda #sir yo'q
}
}
Agar bola class ham foydalanishi kerak bo'lsa — protected pattern (getter orqali):
class Ota {
#sir = "maxfiy";
get _sir() { return this.#sir; } // ← bola uchun himoyalangan kirish
}
class Bola extends Ota {
ochib_ber() {
return this._sir; // ✅ getter orqali
}
}
Xulosa
# — chinakam private maydon. Class tashqarisidan ko'rinmaydi, o'zgartirib bo'lmaydi. JavaScript tili o'zi taqiqlaydi.
Enkapsulatsiya — ichki holatni yashirish. Faqat ruxsat etilgan metodlar orqali o'zgartirish. Bu xatolardan himoya qiladi va kodni ishonchli qiladi.
_ kelishuv, # kafolat.
Keyingi dars
33-dars: Mixin pattern