WisarWisar
Dasturlash kitobi/2-QISM — JavaScript13 daqiqa

2.10-bob: OOP — class, inheritance, encapsulation, polymorphism, static

2-QISM — JavaScript (0 dan chuqurgacha) · 10-mavzu


1. Kirish va motivatsiya

2.5-bobda JS obyekt tizimining ildizini (prototype, this) xom holda ko'rdik — va u biroz "qo'l ishi" edi. Endi uning chiroyli, zamonaviy yuzasiclass sintaksisi va to'liq OOP (Object-Oriented Programming — obyektga yo'naltirilgan dasturlash) ni o'rganamiz.

OOP — katta dasturlarni real dunyo obyektlari sifatida modellashtirish usuli: User, Mahsulot, Buyurtma — har biri o'z ma'lumoti (xususiyat) va xulqi (metod) bilan. Bu — kodni tartibli, qayta ishlatiladigan va kengaytiriladigan qiladi.

O'xshatish: class — bu chizma (blueprint), new bilan yaratilgan obyekt — bino. Bitta chizmadan minglab bino qurish mumkin — har biri alohida, lekin bir xil tuzilishda. User class'idan minglab foydalanuvchi obyekti.

OOP — NestJS (8-QISM) ning butun asosi, TypeScript (7) bilan kuchayadi, va Design Patterns 9.2-bob, SOLID 9.1-bob ning poydevori. Bu bob — katta loyiha arxitekturasining bir ustuni.


2. Nazariya — chuqur tushuntirish

2.1. class — asoslar

class — obyektlar yaratish uchun "chizma". Aslida u prototype 2.5-bob ustiga qurilgan syntactic sugar (chiroyli yuza) — lekin yozish ancha oson:

js
class User {
  // constructor — obyekt YARATILGANDA bir marta ishlaydi
  constructor(ism, yosh) {
    this.ism = ism;       // this — yangi yaratilayotgan obyekt (2.5)
    this.yosh = yosh;
  }

  // metod (prototype'da yashaydi — barcha obyektlar ulashadi, 2.5)
  salomla() {
    return `Salom, men ${this.ism}`;
  }
}

const ali = new User("Ali", 19);   // new — yangi obyekt (2.5)
ali.salomla();                      // "Salom, men Ali"
ali.yosh;                           // 19

new User(...) constructor chaqiriladi this yangi obyektga ishora qiladi (2.5: new binding) obyekt qaytadi.

2.2. OOP ning 4 ustuni

OOP to'rt asosiy prinsipga tayanadi. Ularni bilish — intervyu va arxitektura uchun zarur:

Ustun Ma'nosi
Encapsulation (inkapsulyatsiya) ma'lumotni yashirish, faqat metod orqali murojaat
Inheritance (meros) bir class'ni boshqasidan kengaytirish
Polymorphism (polimorfizm) bir metod har class'da har xil ishlashi
Abstraction (mavhumlashtirish) murakkablikni yashirib, sodda interfeys (0.6)

Quyida har birini ko'ramiz.

2.3. Encapsulation va private (#) maydonlar

Encapsulation — ichki ma'lumotni yashirib, faqat ruxsat etilgan metodlar orqali murojaat (2.4-closure'dagi private g'oyasi). JS'da # (hash) bilan private maydon:

js
class BankHisob {
  #balans = 0;          // PRIVATE — faqat class ICHIDA ko'rinadi

  constructor(boshlangich) {
    this.#balans = boshlangich;
  }

  qoy(summa) {
    if (summa <= 0) return "Noto'g'ri summa";
    this.#balans += summa;
  }
  yech(summa) {
    if (summa > this.#balans) return "Mablag' yetarli emas";  // himoya
    this.#balans -= summa;
  }
  get balans() { return this.#balans; }   // getter orqali o'qish (2.5)
}

const hisob = new BankHisob(100);
hisob.qoy(50);
console.log(hisob.balans);    // 150
// console.log(hisob.#balans); //  SyntaxError — tashqaridan ko'rinmaydi!

Nega private? #balansni faqat class metodlari o'zgartiradi (tekshiruv bilan). Tashqaridan to'g'ridan-to'g'ri hisob.#balans = -1000 qilib bo'lmaydi — ma'lumot himoyalangan. Bu — ishonchli kodning asosi.

2.4. Getter va Setter

Getter/Setter — xususiyatga o'xshab ishlatiladigan, lekin orqasida mantiq bo'lgan metodlar:

js
class Doira {
  #radius;
  constructor(radius) { this.#radius = radius; }

  get yuza() {                      // get — () siz, xususiyat kabi o'qiladi
    return Math.PI * this.#radius ** 2;
  }
  get radius() { return this.#radius; }
  set radius(qiymat) {              // set — tayinlashda mantiq + tekshiruv
    if (qiymat <= 0) throw new Error("Radius musbat bo'lsin");
    this.#radius = qiymat;
  }
}

const d = new Doira(5);
console.log(d.yuza);     // 78.54 — () SIZ! (getter — xususiyat kabi)
d.radius = 10;           // setter ishlaydi (tekshiruv bilan)
// d.radius = -5;        //  Error (setter himoyasi)

2.5. Inheritance — extends va super

Inheritance — bir class boshqasidan meros olib, uni kengaytiradi (2.5-prototypal inheritance'ning chiroyli usuli):

js
class Hayvon {
  constructor(nom) { this.nom = nom; }
  nafasOl() { return `${this.nom} nafas olyapti`; }
  ovoz() { return "..."; }
}

class It extends Hayvon {        // It — Hayvon'dan meros
  constructor(nom, zot) {
    super(nom);                  //  ota constructor'ni chaqir (super — MDN)
    this.zot = zot;              // super'dan KEYIN this ishlatiladi
  }
  ovoz() { return `${this.nom}: Vov!`; }   // metodni qayta yozish (override)
}

const akbar = new It("Akbar", "Alabay");
akbar.nafasOl();   // "Akbar nafas olyapti" (Hayvon'dan meros)
akbar.ovoz();      // "Akbar: Vov!" (It'ning o'zi — override)

super — ota class constructor'i/metodini chaqiradi. Subclass constructor'ida thisdan oldin super() chaqirilishi shart (aks holda xato).

instanceof — obyekt qaysi class'dan (yoki uning otasidan) ekanini tekshiradi. Meros zanjiri bo'ylab ishlaydi:

js
akbar instanceof It;       // true — bevosita o'z class'i
akbar instanceof Hayvon;   // true — ota class ham (meros zanjiri)
akbar instanceof Mushuk;   // false — boshqa shox
akbar instanceof Object;   // true — hammasi Object'dan meros (2.5)

Qachon kerak: turli class obyektlari bir massivda bo'lsa va turiga qarab ish qilmoqchi bo'lganda (if (x instanceof Doira) ...). Lekin ko'p instanceof — polimorfizm 2.6-bob bilan almashtirilsa, kod toza bo'ladi 9.1-bob.

2.6. Polymorphism — bir metod, har xil xulq

Polymorphism — bir xil nomli metod har class'da har xil ishlashi. Yuqorida ovoz()Hayvon, It, Mushukda har xil:

js
class Mushuk extends Hayvon {
  ovoz() { return `${this.nom}: Miyov!`; }
}

const hayvonlar = [new It("Akbar"), new Mushuk("Mosi")];
// Bir xil chaqiriq — har xil natija (polimorfizm)
hayvonlar.forEach(h => console.log(h.ovoz()));
// "Akbar: Vov!"   "Mosi: Miyov!"

Nega kuchli: kod h.ovoz() deydi — qaysi hayvon ekanini bilmasdan. Har class o'z xulqini beradi. Yangi hayvon qo'shsangiz, mavjud kodni o'zgartirmaysiz (9.1: Open/Closed).

2.7. Static — class'ning o'ziga tegishli

static metod/maydon — obyektga emas, class'ning o'ziga tegishli; obyekt yaratmasdan chaqiriladi:

js
class MathUtil {
  static PI = 3.14159;
  static kvadrat(n) { return n * n; }   // static metod
}

MathUtil.kvadrat(5);    // 25 — obyekt YARATMASDAN, class orqali
MathUtil.PI;            // 3.14159
// new MathUtil().kvadrat() — ishlamaydi (static — obyektda emas)

// Klassik misol — factory yoki utility
class User {
  constructor(ism) { this.ism = ism; }
  static yaratMehmon() { return new User("Mehmon"); }  // factory (9.2)
}
const mehmon = User.yaratMehmon();

Qachon static: utility funksiyalar (Math.max ham static), factory metodlar, hisoblagichlar (umumiy holat) — obyektga bog'liq bo'lmagan narsalar.

Static blok (static { ... }) — static maydonlarni murakkab mantiq bilan bir marta (class yuklanganda) tayyorlash uchun (MDN, ES2022):

js
class Konfig {
  static manbalar;
  static {                          // class e'lon qilinganda BIR marta ishlaydi
    const xom = ["db", "cache", "log"];
    Konfig.manbalar = xom.map(m => m.toUpperCase());
  }
}
Konfig.manbalar;   // ["DB", "CACHE", "LOG"]

Nega kerak: oddiy static x = ... bitta ifoda bilan cheklangan; static blokda bir nechta qator, try/catch, sikl ishlatib, static holatni to'liq sozlash mumkin.

2.8. class aslida prototype (2.5 bilan bog'lanish)

Eslatma: class — yangi narsa emas, balki prototype 2.5-bob ning chiroyli yozuvi:

js
class User { salomla() {} }
// aslida ≈
function User() {}
User.prototype.salomla = function() {};

Metodlar prototypeda (barcha obyektlar ulashadi — 2.5, xotira tejash); this — har bir obyekt. Shuning uchun 2.5-bobni tushunish — classni chuqur tushunish demak.


3. Sintaksis — tez ma'lumotnoma

js
class Nom extends Ota {
  #private = 0;              // private maydon (2.3)
  static umumiy = 0;        // static maydon (2.7)

  constructor(p) {
    super(p);               // ota constructor (meros — 2.5)
    this.x = p;
  }

  metod() {}                // oddiy metod (prototype'da)
  get xususiyat() {}        // getter (2.4)
  set xususiyat(v) {}       // setter (2.4)
  static yordam() {}        // static metod (2.7)
  static { /* ... */ }      // static blok — bir marta sozlash (2.7)
}

const obj = new Nom(arg);   // obyekt yaratish
obj instanceof Nom;         // turini tekshirish — true (2.5)

4. Batafsil kod namunalari

Misol 1 — To'liq class (encapsulation + getter/setter)

js
class Mahsulot {
  #narx;                              // private (2.3)
  constructor(nom, narx) {
    this.nom = nom;
    this.#narx = narx;
  }
  get narx() { return this.#narx; }   // getter (2.4)
  set narx(yangi) {                    // setter + tekshiruv
    if (yangi < 0) throw new Error("Narx manfiy bo'lmasin");
    this.#narx = yangi;
  }
  get narxFormat() {                   // hisoblangan getter
    return `${this.#narx.toLocaleString("uz")} so'm`;  // (2.6)
  }
  chegirma(foiz) { this.#narx *= (1 - foiz / 100); }
}

const olma = new Mahsulot("Olma", 12000);
console.log(olma.narxFormat);   // "12 000 so'm"
olma.chegirma(25);
console.log(olma.narx);         // 9000

Misol 2 — Inheritance va polymorphism (2.5, 2.6)

js
class Shakl {
  constructor(nom) { this.nom = nom; }
  yuza() { return 0; }                // bola override qiladi
  tasvir() { return `${this.nom}: yuza = ${this.yuza().toFixed(2)}`; }
}
class Doira extends Shakl {
  constructor(r) { super("Doira"); this.r = r; }
  yuza() { return Math.PI * this.r ** 2; }   // override (2.6)
}
class Kvadrat extends Shakl {
  constructor(t) { super("Kvadrat"); this.t = t; }
  yuza() { return this.t ** 2; }
}

const shakllar = [new Doira(5), new Kvadrat(4)];
shakllar.forEach(s => console.log(s.tasvir()));   // polimorfizm (2.6)
// "Doira: yuza = 78.54"   "Kvadrat: yuza = 16.00"

Misol 3 — Static (factory va hisoblagich) (2.7)

js
class User {
  static soni = 0;                    // umumiy hisoblagich (static)
  #id;
  constructor(ism) {
    this.ism = ism;
    this.#id = ++User.soni;           // har obyektga noyob id
  }
  get id() { return this.#id; }

  static yaratAdmin(ism) {            // factory metod (9.2)
    const u = new User(ism);
    u.admin = true;
    return u;
  }
}

const a = new User("Ali");
const v = User.yaratAdmin("Vali");
console.log(a.id, v.id);             // 1 2
console.log(User.soni);              // 2 (umumiy)

Misol 4 — Meros zanjiri (super metod chaqiruvi)

js
class Hayvon {
  constructor(nom) { this.nom = nom; }
  tasvir() { return `Bu ${this.nom}`; }
}
class It extends Hayvon {
  tasvir() {
    // ota metodini chaqirib, kengaytirish (super — 2.5)
    return `${super.tasvir()}, u it`;
  }
}
console.log(new It("Akbar").tasvir());   // "Bu Akbar, u it"

5. To'g'ri va noto'g'ri holatlar

1) Subclass constructor'ida super()ni unutish

js
//  ReferenceError — super'dan oldin this (2.5)
class It extends Hayvon {
  constructor(nom) { this.nom = nom; }   // super() yo'q!
}

//  avval super()
class It extends Hayvon {
  constructor(nom) { super(nom); this.zot = "..."; }
}

2) Ma'lumotni public qoldirish (private o'rniga)

js
//  tashqaridan buzilishi mumkin (2.3)
class Hisob { constructor(b) { this.balans = b; } }
hisob.balans = -99999;   // hech qanday himoya yo'q!

//  private + metod
class Hisob { #balans; /* faqat metod orqali */ }

3) Getter'ni () bilan chaqirish

js
//  getter — xususiyat kabi, () SIZ (2.4)
d.yuza();    // TypeError (yuza — son, funksiya emas)

// 
d.yuza;

4) Hamma narsani class qilish

js
//  oddiy ma'lumot/funksiya uchun keraksiz class
class Yordamchi { static qosh(a, b) { return a + b; } }

//  oddiy funksiya yetadi (2.3)
const qosh = (a, b) => a + b;

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — Must call super constructor before accessing 'this'

Sababi: subclass constructor'ida thisdan oldin super() chaqirilmadi 2.5-bob. Yechimi: constructorning birinchi qatorida super(...).

Xato 2 — Cannot read private member #x

Sababi: private maydonga class tashqarisidan murojaat 2.3-bob. Yechimi: getter/metod orqali; faqat class ichida #.

Xato 3 — TypeError: X is not a constructor

Sababi: newsiz class chaqirildi yoki static metodni obyektda. Yechimi: obyekt — new Class(); static — Class.metod().

Xato 4 — Metod this yo'qotadi (callback'da)

js
setTimeout(obj.metod, 1000);   //  this yo'qoladi (2.5)

Sababi: metod ajratilganda this bog'lanishi yo'qoladi 2.5-bob. Yechimi: arrow bilan o'ra (() => obj.metod()) yoki bind 2.5-bob.

Xato 5 — Chuqur meros zanjiri (murakkablik)

Sababi: 4-5 daraja meros — chalkash, mo'rt. Yechimi: "composition over inheritance" — meros o'rniga obyektlarni birlashtirish (9.1, 9.3); meros faqat haqiqiy "is-a" munosabatda.


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • Prototype 2.5-bob: class — prototype ustiga sugar; this, meros mexanizmi.
  • TypeScript (7): class + tip; interface, implements, abstract — OOP kuchayadi.
  • NestJS (8): butun framework class asosida (controller, service, module — DI).
  • Design Patterns 9.2-bob: Singleton, Factory (Misol 3), Observer — class bilan.
  • SOLID 9.1-bob: Single Responsibility, Open/Closed (polimorfizm — 2.6).
  • React (eski): class komponentlar (hozir function — 11.2, lekin uchraydi).
  • DB ORM (6.11–6.13): entity'lar — class (TypeORM, Prisma model).

8. Eng yaxshi amaliyotlar (best practices)

  • Ma'lumotni private (#) qiling, metod orqali murojaat — encapsulation 2.3-bob.
  • Getter/setter bilan tekshiruvli murojaat 2.4-bob; getter — () siz.
  • Subclass constructor'ida birinchi super() 2.5-bob.
  • Polimorfizm bilan if/switch o'rniga — har class o'z xulqini beradi (2.6, 9.1).
  • "Composition over inheritance" — chuqur meros o'rniga birlashtirish (6-bo'lim, 9.3).
  • Static — utility/factory uchun 2.7-bob; obyektga bog'liq bo'lmaganda.
  • Hamma narsani class qilmang — oddiy ma'lumot/funksiya yetsa, undan foydalaning (5-bo'lim).
  • Bitta class — bitta mas'uliyat (Single Responsibility — 9.1).

9. Amaliy loyiha: "Kutubxona Boshqaruv Tizimi (OOP)"

OOP ning 4 ustunini to'liq ishlatadigan tizim.

Maqsad

class, encapsulation (private), getter/setter, inheritance, polymorphism va static'ni amalda qo'llab, real domenni OOP bilan modellashtirish.

Talablar (requirements)

  1. Kitob class: nom, muallif, private #band (band/bo'sh holat); band()/qaytar() metodlari; holat getter (2.3, 2.4).
  2. Meros: Kitobdan ElektronKitob (qo'shimcha format) va AudioKitob (qo'shimcha davomiylik) — super bilan 2.5-bob.
  3. Polymorphism: har class'da tasvir() metodi har xil 2.6-bob; ro'yxat bo'ylab bir xil chaqiruv (Misol 2).
  4. Foydalanuvchi class: private #olinganKitoblar massivi; ol(kitob)/qaytar(kitob) (tekshiruv bilan — encapsulation).
  5. Static: Kitob.soni hisoblagich (har yaratilganda oshadi); Kitob.yaratNamuna() factory (2.7, Misol 3).
  6. Getter/setter: kamida bitta tekshiruvli setter (masalan reyting 1–5 oralig'i) 2.4-bob.
  7. Himoya isboti: private maydonga tashqaridan murojaat qilib bo'lmasligini ko'rsating 2.3-bob.
  8. (Bonus) Kutubxona class — kitoblar to'plami; qidir, bandlar, bo'shlar (Array metodlari — 2.7).

Maslahatlar (hint)

  • Private: #band = false; — faqat metod ichida o'zgartiring.
  • Meros: class ElektronKitob extends Kitob { constructor(...) { super(...); ... } } 2.5-bob.
  • Polimorfizm: har class tasvir()ni override qilsin; kitoblar.forEach(k => k.tasvir()) 2.6-bob.
  • Static hisoblagich: static soni = 0; constructor'da Kitob.soni++ (Misol 3).
  • Setter tekshiruvi: set reyting(v) { if (v<1||v>5) throw...; } 2.4-bob.

"Tayyor" mezonlari (acceptance criteria)

  • Kitob class private maydon va getter/setter bilan.
  • Meros (extends + super) ishlaydi.
  • Polimorfizm: tasvir() har class'da har xil, bir xil chaqiruv.
  • Encapsulation: band holat faqat metod orqali o'zgaradi.
  • Static hisoblagich va factory ishlaydi.
  • Tekshiruvli setter mavjud.
  • Private maydon tashqaridan ko'rinmasligi isbotlangan.

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda OOP va class ni o'rgandik:

  • class — prototype 2.5-bob ustiga chiroyli yuza; constructor (newda ishlaydi), metodlar (prototype'da), this — obyekt.
  • 4 ustun: encapsulation (private #, metod orqali), inheritance (extends/super), polymorphism (override — bir metod, har xil xulq), abstraction.
  • Getter/setter — xususiyat kabi, lekin mantiq/tekshiruv bilan (() siz).
  • static — class'ning o'ziga tegishli (utility, factory, hisoblagich); static { } blok bilan bir marta sozlash.
  • instanceof — obyekt qaysi class'dan ekanini meros zanjiri bo'ylab tekshiradi 2.5-bob.
  • Best: private bilan himoya, polimorfizm bilan if o'rniga, "composition over inheritance".

Keyingi bob — 2.11-bob: Asinxron JS — callback, Promise, async/await, fetch. Bu — JS'ning eng muhim va eng ko'p so'raladigan mavzularidan biri. 0.5-bobda ko'rgan event loop, 0.4-dagi so'rovlar — hammasi shu yerda birlashadi. Tarmoqdan ma'lumot olish, fayl o'qish, kutish — bularning hammasi asinxron. Promise va async/awaitsiz zamonaviy JS yo'q.


Foydalanilgan rasmiy/ishonchli manbalar

  • MDN Web Docs — Classes, constructor, extends/super, static
  • MDN Web Docs — Private elements (#), private class fields
  • MDN Web Docs — getter/setter, Using classes
  • MDN Web Docs — instanceof, static initialization blocks

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
2.10-bob: OOP — class, inheritance, encapsulation, polymorphism, static — Wisar