Klasslar

Klass merosi

Klass merosi (inheritance) โ€” bir klassning imkoniyatlarini boshqa klass asosida kengaytirish usuli. Bu bizga mavjud funksionallikni takrorlamasdan qayta ishlatish imkonini beradi.

"extends" kalit so'zi

Aytaylik, Animal (hayvon) klassimiz bor:

meros-animal.js
// natija shu yerda chiqadi

Endi Rabbit (quyon) klassini yaratmoqchimiz. Quyon ham hayvon bo'lgani uchun, u Animal imkoniyatlarini meros olishi va o'ziga xos metodlar qo'shishi kerak. Buning uchun extends ishlatamiz:

meros-extends.js
// natija shu yerda chiqadi

Rabbit obyekti ham o'zining hide() metodiga, ham Animaldan meros olingan run() metodiga kirish huquqiga ega.

Texnik jihatdan extends Rabbit.prototype.[[Prototype]]ni Animal.prototypega bog'laydi. Shu sababli Rabbitda metod topilmasa, JavaScript uni Animal.prototypedan qidiradi โ€” bu prototip zanjiri orqali ishlaydi.

extendsdan keyin ifoda ham yozilishi mumkin. Masalan, klass generatsiya qiluvchi funksiya chaqiruvi:

function f(phrase) {
  return class {
    sayHi() { return phrase; }
  };
}

class User extends f("Salom") {}

console.log(new User().sayHi()); // Salom

Metodni qayta aniqlash (override)

Endi keling, oldinga borib, metodni qayta aniqlaymiz (override qilamiz). Standart holatda Rabbitda aniqlanmagan barcha metodlar Animaldan "o'z holicha" olinadi. Ammo agar biz Rabbitda o'z stop()imizni yozsak, u ishlatiladi:

meros-override.js
// natija shu yerda chiqadi

super orqali ota metodni chaqirish

Ko'pincha biz ota metodni butunlay almashtirmoqchi emasmiz โ€” uni asos qilib, ustiga qo'shimcha qilmoqchimiz. Buning uchun super.method(...) orqali ota klassdagi metodni chaqiramiz:

meros-super-method.js
// natija shu yerda chiqadi

Bu yerda Rabbitning stop() metodi o'zining zanjiridagi super.stop()ni chaqiradi โ€” ya'ni Animal.prototype.stopni.

Strelka funksiyalarda o'zining supersi yo'q. Agar strelka funksiya ichida superga murojaat qilsangiz, u tashqi metoddan olinadi. Bu ko'pincha foydali xususiyat, chunki strelka funksiyada super "yo'qolib" qolmaydi.

Konstruktorni qayta aniqlash

Konstruktor bilan biroz murakkabroq. Hozirgacha Rabbitning o'z constructori yo'q edi. Spetsifikatsiyaga ko'ra, agar meros olgan klassda constructor bo'lmasa, quyidagi "bo'sh" konstruktor avtomatik yaratiladi:

class Rabbit extends Animal {
  // meros olgan klass uchun avtomatik generatsiya qilinadi
  constructor(...args) {
    super(...args);
  }
}

Ko'rib turganingizdek, u shunchaki ota constructorini chaqiradi va unga barcha argumentlarni uzatadi. Endi Rabbitga o'z konstruktorimizni qo'shsak, unda albatta super(...)ni chaqirishimiz kerak:

meros-super-ctor.js
// natija shu yerda chiqadi

Nima uchun super() shart?

Meros olgan klass konstruktorlari maxsus ichki [[ConstructorKind]]: "derived" belgisiga ega. Bu farq juda muhim:

Agar meros olgan konstruktorda super()ni chaqirmasangiz yoki thisga undan oldin murojaat qilsangiz, xatolik chiqadi: "Must call super constructor before accessing 'this'".
meros-super-error.js
// natija shu yerda chiqadi

Xulosa