25 август 2025

Klass meros olish (Class inheritance)

Klass meros olish — bu bitta klassni boshqasidan kengaytirish (extend) usuli.

Shunday qilib, biz mavjud funksionallik ustiga yangi funksionallik qo‘shishimiz mumkin.

extends kalit so‘zi

Keling, bizda Animal klassi bor, deylik:

class Animal {
  constructor(name) {
    this.speed = 0;
    this.name = name;
  }
  run(speed) {
    this.speed = speed;
    alert(`${this.name} ${this.speed} tezlikda yugurmoqda.`);
  }
  stop() {
    this.speed = 0;
    alert(`${this.name} joyida to‘xtadi.`);
  }
}

let animal = new Animal("Mening hayvonim");

animal obyektini va Animal klassini grafik ko‘rinishda tasavvur qilishimiz mumkin:

…Endi biz Rabbit nomli boshqa klass yaratmoqchimiz.

Quyonlar ham hayvon bo‘lgani uchun, Rabbit klassi Animal asosida bo‘lishi kerak. Shunday qilib, u hayvon metodlariga ham ega bo‘ladi va qo‘shimcha ravishda o‘zining metodlariga ham ega bo‘ladi.

Sintaksis: class Bola extends Ota.

Keling, Animaldan meros oluvchi Rabbit klassini yarataylik:

class Rabbit extends Animal {
  hide() {
    alert(`${this.name} yashirinmoqda!`);
  }
}

let rabbit = new Rabbit("Oq Quyon");

rabbit.run(5); // Oq Quyon 5 tezlikda yugurmoqda.
rabbit.hide(); // Oq Quyon yashirinmoqda!

Rabbit klassidan olingan obyekt ham Rabbit metodlariga (masalan, rabbit.hide()), ham Animal metodlariga (masalan, rabbit.run()) ega.

extends kalit so‘zi ichki ishlash jarayonida prototip mexanizmidan foydalanadi. U Rabbit.prototype.[[Prototype]]ni Animal.prototypega o‘rnatadi. Agar metod Rabbit.prototypeda topilmasa, JavaScript uni Animal.prototypedan qidiradi.

Metodni qidirish jarayoni (masalan rabbit.run):

  1. rabbit obyektida qidiradi (run yo‘q).
  2. Rabbit.prototypeda qidiradi (hide bor, run yo‘q).
  3. Animal.prototypeda qidiradi (bu yerda run mavjud).

JavaScript’ning o‘zidagi built-in obyektlar ham shu meros olish mexanizmidan foydalanadi. Masalan, Date.prototype.[[Prototype]] bu Object.prototype.

Metodni qayta yozish (Overriding a method)

Agar Rabbit klassida yangi metod yozmasak, u avtomatik ravishda Animal metodlaridan foydalanadi.
Lekin agar biz o‘zimiz metod yozsak, u holda eski metod o‘rniga yangisi ishlatiladi:

class Rabbit extends Animal {
  stop() {
    // endi bu metod `rabbit.stop()` chaqirilganda ishlatiladi
  }
}

Ko‘pincha biz ota metodni butunlay almashtirishni istamaymiz, balki uning ustiga qo‘shimcha logika qo‘shmoqchimiz. Buning uchun super kalit so‘zi ishlatiladi:

  • super.method(...) → ota metodni chaqirish.
  • super(...) → ota konstruktorga murojaat (faqat konstruktor ichida).

Misol: quyon to‘xtaganda avtomatik yashirinsin:

class Rabbit extends Animal {
  hide() {
    alert(`${this.name} yashirinmoqda!`);
  }

  stop() {
    super.stop(); // ota klassning stop() metodi
    this.hide(); // qo‘shimcha xatti-harakat
  }
}

Konstruktorni qayta yozish (Overriding constructor)

Agar bola klassda konstruktor yozilmasa, u avtomatik ravishda ota konstruktorni chaqiradigan “bo‘sh” konstruktor yaratiladi:

class Rabbit extends Animal {
  constructor(...args) {
    super(...args);
  }
}

Agar o‘zimiz konstruktor yozsak, albatta super(...)ni chaqirishimiz shart. Aks holda this mavjud bo‘lmaydi va xato chiqadi.

class Rabbit extends Animal {
  constructor(name, earLength) {
    super(name); // ota klass konstruktorini chaqirish
    this.earLength = earLength;
  }
}

Muhim eslatma: metodlar va maydonlarni (fields) qayta yozish

Metodlar qayta yozilganda ota klass konstruktori yangisini chaqiradi.
Lekin klass maydonlari (fields) bilan bunday emas — ular faqat super()dan keyin ishga tushadi. Shu sababli ota konstruktor ichida doim ota klass maydoni ishlatiladi.

Misol:

class Animal {
  name = "animal";
  constructor() {
    alert(this.name);
  }
}

class Rabbit extends Animal {
  name = "rabbit";
}

new Rabbit(); // animal

Metodlar esa boshqacha ishlaydi — ular qayta yozilganda yangisi ishlaydi.

Xulosa

  1. Klassni kengaytirish: class Bola extends Ota.
    • Bola.prototype.__proto__ = Ota.prototype
  2. Konstruktor qayta yozilganda:
    • super() chaqirilishi kerak va this dan oldin bo‘lishi shart.
  3. Metodlarni qayta yozishda:
    • super.method() orqali ota metodni chaqirish mumkin.
  4. Ichki mexanizmlar:
    • Metodlar [[HomeObject]]ga ega va shu orqali super ishlaydi.
    • super ishlatadigan metodni boshqa obyektga ko‘chirish mumkin emas.

Eslatma: Arrow function’larda o‘zining this yoki superi yo‘q, ular tashqi kontekstdan foydalanadi.

Vazifalar

Rabbit kengaytirilgan Animal kodi.

Afsuski, Rabbit obyektlarini yaratish mumkin emas. Nima bo’ldi? Tuzating.

class Animal {

  constructor(name) {
    this.name = name;
  }

}

class Rabbit extends Animal {
  constructor(name) {
    this.name = name;
    this.created = Date.now();
  }
}

let rabbit = new Rabbit("White Rabbit"); // Error: this is not defined
alert(rabbit.name);

Buning sababi, bola konstruktor super() ni chaqirishi kerak.

Mana tuzatilgan kod:

class Animal {

  constructor(name) {
    this.name = name;
  }

}

class Rabbit extends Animal {
  constructor(name) {
    super(name);
    this.created = Date.now();
  }
}

let rabbit = new Rabbit("White Rabbit"); //yaxshi hozir
alert(rabbit.name); // White Rabbit

Bizda soat klassi bor. Hozirda u har soniyada vaqtni bosib chiqaradi.

class Clock {
  constructor({ template }) {
    this.template = template;
  }

  render() {
    let date = new Date();

    let hours = date.getHours();
    if (hours < 10) hours = "0" + hours;

    let mins = date.getMinutes();
    if (mins < 10) mins = "0" + mins;

    let secs = date.getSeconds();
    if (secs < 10) secs = "0" + secs;

    let output = this.template
      .replace("h", hours)
      .replace("m", mins)
      .replace("s", secs);

    console.log(output);
  }

  stop() {
    clearInterval(this.timer);
  }

  start() {
    this.render();
    this.timer = setInterval(() => this.render(), 1000);
  }
}

Clock dan meros qilib yangi ExtendedClock klassini yarating va aniqlik parametrini qo’shadi – “shomlar” orasidagi ms soni. Sukut bo’yicha 1000 (1 soniya) bo’lishi kerak.

  • Sizning kodingiz Extended-clock.js faylida bo’lishi kerak
  • Asl clock.js ni o’zgartirmang. Uni kengaytiring.

Vazifa uchun sandbox-ni oching.

class ExtendedClock extends Clock {
  constructor(options) {
    super(options);
    let { precision = 1000 } = options;
    this.precision = precision;
  }

  start() {
    this.render();
    this.timer = setInterval(() => this.render(), this.precision);
  }
}

Yechimni sandbox-da oching.

O'quv qo'llanma xaritasi

Izohlar

izoh berishdan oldin buni o'qing…
  • Agar sizda nimani yaxshilash kerakligi haqida takliflaringiz bo'lsa - iltimos, GitHub muammosini yuboring yoki izoh berish o'rniga so'rov yuboring.
  • Agar siz maqolada biror narsani tushunolmasangiz - iltimos, batafsilroq ma'lumot bering.
  • Bir nechta so'z so'zlarini kiritish uchun <code> yorlig'ini ishlating, bir nechta satrlar uchun - ularni <pre> yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepen…)