10-bo‘lim
Sinflar
Parametr xossalari, private va #, implements, abstract va sinflardagi uchta kutilmagan xatti-harakat.
Ushbu bo‘lim mundarijasi
- Sinf asosi
- Parametr xossalari
- Ko'rinish belgilari
- Birinchi kutilmagan narsa: private ish vaqtida yo'q
- Ikkinchi kutilmagan narsa: private tuzilmaviy turlashni buzadi
- implements
- Maydon albatta to'ldirilishi kerak
- Getter va setter
- abstract va static
- Uchinchi kutilmagan narsa: metod this ni yo'qotadi
- Xulosa
Sinflar TypeScript ning ixtirosi emas - ular JavaScript da bor.
TypeScript ularga turlar, ko'rinish belgilari va implements
qo'shadi.
Bu bobda uchta kutilmagan narsa bor: private ish vaqtida
yo'qoladi, private tuzilmaviy turlashni buzadi, va metod
o'zining this ini yo'qotadi.
Sinf asosi #
class Mahsulot {
nomi: string;
narx: number;
constructor(nomi: string, narx: number) {
this.nomi = nomi;
this.narx = narx;
}
chegirma(foiz: number): number {
return this.narx - (this.narx * foiz) / 100;
}
}
const m = new Mahsulot("Olma", 12000);
console.log(m.nomi, m.chegirma(20));
tsx src/sinf.ts
Olma 9600
Maydonlar sinf tanasida e'lon qilinadi, konstruktorda to'ldiriladi.
Parametr xossalari #
Yuqoridagi kodda nomi uch marta yozildi. TypeScript buni
qisqartiradi:
class Mahsulot {
constructor(
public nomi: string,
private narx: number,
readonly id: number = 1,
) {}
chop(): string {
return `${this.nomi}: ${this.narx}`;
}
}
const m = new Mahsulot("Olma", 12000);
console.log(m.chop(), m.nomi, m.id);
tsx src/param.ts
Olma: 12000 Olma 1
Konstruktor parametriga public, private, protected yoki
readonly qo'yilsa, TypeScript maydonni o'zi yaratib, qiymatni
o'zi tayinlaydi. Sinf tanasi butunlay bo'sh qoldi.
Parametr xossalari JavaScript da yo'q. Kod JavaScript ga
o'girilganda ular oddiy this.nomi = nomi; qatorlariga
aylanadi.
Bu - darslikdagi kam sonli "faqat TypeScript da bor"
imkoniyatlardan biri. Qolganlari: enum, namespace va
parametr dekoratorlari.
Ko'rinish belgilari #
class Mahsulot {
constructor(private narx: number) {}
}
const m = new Mahsulot(12000);
console.log(m.narx);
tsc --noEmit 2>&1 | fold -sw 74
src/priv.ts(6,15): error TS2341: Property 'narx' is private and only
accessible within class 'Mahsulot'.
| Belgi | Kim ko'radi |
|---|---|
public (standart) | Hamma |
protected | Sinf va undan meros olganlar |
private | Faqat shu sinf |
Birinchi kutilmagan narsa: private ish vaqtida yo'q #
class Mahsulot {
constructor(private narx: number) {}
}
const m = new Mahsulot(12000);
console.log(JSON.stringify(m));
console.log(Object.keys(m).join(","));
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/priv2.ts
tsc: xato yo_q
{"narx":12000}
narx
narx JSON.stringify da ham, Object.keys da ham ko'rinib
turibdi. private - faqat kompilyator uchun; kod JavaScript ga
o'girilganda u yo'qoladi.
Haqiqiy shaxsiy maydon uchun JavaScript ning # yozuvi bor:
class Mahsulot {
#narx: number;
constructor(narx: number) {
this.#narx = narx;
}
chop(): string {
return String(this.#narx);
}
}
const m = new Mahsulot(12000);
console.log(m.chop());
console.log(JSON.stringify(m));
console.log(Object.keys(m).length);
tsx src/xesh.ts
12000
{}
0
#narx tashqaridan umuman ko'rinmaydi - na JSON da, na
Object.keys da, na as any orqali.
| Maqsad | Tanlov |
|---|---|
| Jamoaga "bunga tegmang" deyish | private |
| Maxfiy ma'lumotni yashirish | # |
| Kutubxona API sini yopish | # |
JSON.stringify dan chiqarib tashlash | # |
private - hujjat, # - qulf.
Ikkinchi kutilmagan narsa: private tuzilmaviy turlashni buzadi #
8-bobda ko'rdik: TypeScript nomga emas, tuzilmaga qaraydi. Sinflarda bitta istisno bor:
class A {
constructor(private x: number) {}
}
class B {
constructor(private x: number) {}
}
let a: A = new A(1);
const b: B = new B(2);
a = b;
tsc --noEmit 2>&1 | fold -sw 74
src/tuzilma.ts(11,1): error TS2322: Type 'B' is not assignable to type
'A'.
Types have separate declarations of a private property 'x'.
Ikkala sinf bir xil - bir xil nomli, bir xil turdagi maydon.
Lekin private maydonlar alohida e'lon qilingan bo'lgani
uchun mos kelmadi.
private ni olib tashlasak:
class A {
constructor(public x: number) {}
}
class B {
constructor(public x: number) {}
}
let a: A = new A(1);
const b: B = new B(2);
a = b;
console.log(a.x);
tsx src/tuzilma2.ts
2
Endi ishladi. Ya'ni private sinfga nomga asoslangan
xatti-harakat qo'shadi - bu butun tur tizimidagi yagona joy.
Teskari tomoni ham qiziq - oddiy obyekt sinf turiga mos keladi:
class Mahsulot {
constructor(public nomi: string) {}
}
const m: Mahsulot = { nomi: "Olma" };
console.log(m.nomi, m instanceof Mahsulot);
tsx src/obyekt.ts
Olma false
new ishlatilmadi, lekin tur mos keldi - chunki tuzilma bir
xil. instanceof esa false qaytardi. Test yozishda bu
foydali, lekin instanceof ga tayanadigan kodda xavfli.
implements #
interface Sotiladigan {
nomi: string;
narxi(): number;
}
class Mahsulot implements Sotiladigan {
constructor(
public nomi: string,
private asos: number,
) {}
narxi(): number {
return this.asos;
}
}
const m = new Mahsulot("Olma", 12000);
console.log(m.nomi, m.narxi());
tsx src/implem.ts
Olma 12000
interface Sotiladigan {
nomi: string;
narxi(): number;
}
class Mahsulot implements Sotiladigan {
constructor(public nomi: string) {}
}
tsc --noEmit 2>&1 | fold -sw 74
src/implem2.ts(6,7): error TS2420: Class 'Mahsulot' incorrectly
implements interface 'Sotiladigan'.
Property 'narxi' is missing in type 'Mahsulot' but required in type
'Sotiladigan'.
implements faqat tekshiradi - u sinfga hech narsa
qo'shmaydi va ish vaqtida iz qoldirmaydi.
Maydon albatta to'ldirilishi kerak #
class Mahsulot {
nomi: string;
narx: number = 0;
}
tsc --noEmit 2>&1 | fold -sw 74
src/init.ts(2,3): error TS2564: Property 'nomi' has no initializer and is
not definitely assigned in the constructor.
Bu strictPropertyInitialization ning ishi (u strict ga
kiradi). narx ga standart qiymat berilgani uchun shikoyat
yo'q.
Uchta yechim: standart qiymat berish, konstruktorda
to'ldirish, yoki turni string | undefined qilish.
Getter va setter #
class Mahsulot {
#narx = 0;
get narx(): number {
return this.#narx;
}
set narx(yangi: number) {
if (yangi < 0) throw new Error("manfiy narx");
this.#narx = yangi;
}
}
const m = new Mahsulot();
m.narx = 12000;
console.log(m.narx);
try {
m.narx = -5;
} catch (e) {
console.log((e as Error).message);
}
tsx src/getset.ts
12000
manfiy narx
m.narx oddiy maydondek ko'rinadi, aslida metod chaqiriladi.
catch (e) dagi e ning turi - unknown, Error emas. Buni
strict ichidagi useUnknownInCatchVariables talab qiladi,
chunki JavaScript da istalgan qiymatni tashlash mumkin.
abstract va static #
abstract class Shakl {
static sanoq = 0;
constructor() {
Shakl.sanoq++;
}
abstract yuza(): number;
chop(): string {
return `yuza: ${this.yuza().toFixed(1)}`;
}
}
class Kvadrat extends Shakl {
constructor(private tomon: number) {
super();
}
yuza(): number {
return this.tomon ** 2;
}
}
const k = new Kvadrat(3);
console.log(k.chop(), Shakl.sanoq);
tsx src/abstr.ts
yuza: 9.0 1
chop() this.yuza() ni chaqiradi - garchi Shakl uning
tanasini bilmasa ham. Bu - shablon naqshi.
abstract class Shakl {
abstract yuza(): number;
}
const s = new Shakl();
tsc --noEmit 2>&1 | fold -sw 74
src/abstr2.ts(5,11): error TS2511: Cannot create an instance of an
abstract class.
Uchinchi kutilmagan narsa: metod this ni yo'qotadi #
class Hisob {
#jami = 0;
qosh(n: number): void {
this.#jami += n;
}
get jami(): number {
return this.#jami;
}
}
const h = new Hisob();
[1, 2, 3].forEach(h.qosh);
console.log(h.jami);
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/this1.ts 2>&1 | grep -oE "TypeError.*" | head -1
tsc: xato yo_q
TypeError: Cannot read properties of undefined (reading '#jami')
h.qosh - shunchaki funksiya qiymati. U h dan ajratilganda
this bilan bog'lanishini yo'qotadi. Bu JavaScript ning
qoidasi, TypeScript uni standart holatda tekshirmaydi.
Eng oddiy yechim - metodni strelkali xossa qilish:
class Hisob {
#jami = 0;
qosh = (n: number): void => {
this.#jami += n;
};
get jami(): number {
return this.#jami;
}
}
const h = new Hisob();
[1, 2, 3].forEach(h.qosh);
console.log(h.jami);
tsx src/this2.ts
6
Strelkali funksiya this ni yaratilgan joydan oladi va uni
hech qachon yo'qotmaydi.
Muammoni kompilyatsiyada tutish ham mumkin - this
parametri orqali:
class Hisob {
#jami = 0;
qosh(this: Hisob, n: number): void {
this.#jami += n;
}
}
const h = new Hisob();
const f = h.qosh;
f(1);
tsc --noEmit 2>&1 | fold -sw 74
src/this3.ts(11,1): error TS2684: The 'this' context of type 'void' is
not assignable to method's 'this' of type 'Hisob'.
this: Hisob - soxta birinchi parametr. U ish vaqtida mavjud
emas, lekin kompilyatorga "bu metodni Hisob nusxasidan
ajratmang" deb aytadi.
qosh = (n) => {...} har bir nusxa uchun alohida funksiya
yaratadi. Oddiy metod esa prototipda bir marta saqlanadi.
| Xotira | this | |
|---|---|---|
| Metod | Bitta nusxa | Yo'qolishi mumkin |
| Strelkali xossa | Har obyektda | Doim bog'langan |
Minglab obyekt yaratilmasa, farq sezilmaydi. Shubhali
joylarda esa this: Hisob parametri bepul himoya beradi.
Xulosa #
- Sinf maydonlariga tur yoziladi; konstruktor parametrlariga
public/private/readonlyqo'yilsa, maydon avtomatik yaratiladi. - Parametr xossalari - TypeScript ga xos imkoniyat, JavaScript da yo'q.
privatevaprotectedfaqat kompilyatorda ishlaydi - JavaScript ga o'girilganda yo'qoladi.#maydon- JavaScript ning haqiqiy shaxsiy maydoni; uJSON.stringifyvaObject.keysda ko'rinmaydi.privatemaydonli ikkita bir xil sinf bir-biriga mos kelmaydi - bu tuzilmaviy turlashdagi yagona istisno.- Oddiy obyekt sinf turiga mos keladi, lekin
instanceoffalseqaytaradi. implementsfaqat tekshiradi; sinfga hech narsa qo'shmaydi.strictPropertyInitializationhar bir maydonni to'ldirishni talab qiladi (TS2564).catch (e)dagie-unknown; ishlatishdan oldin tekshirish yokias Errorkerak.abstractsinfdan nusxa yasab bo'lmaydi;abstractmetod merosxo'rda amalga oshiriladi.- Metod nusxadan ajratilganda
thisni yo'qotadi - strelkali xossa yokithis: Sinfparametri bilan himoyalaning.
- Ikkita maydonli va bitta metodli sinf yozing.
- Uni parametr xossalari bilan qayta yozib, qatorlar sonini solishtiring.
privatemaydonniJSON.stringifybilan chop etib, ko'rinishini tasdiqlang.- Uni
#ga o'zgartirib, natijaning{}bo'lishini ko'ring. - Bir xil
privatemaydonli ikkita sinf yozib,TS2322ni oling. - Sinf turidagi o'zgaruvchiga oddiy obyekt bering va
instanceofnatijasini tekshiring. interfaceyozib, uniimplementsqiling va bir metodni ataylab unuting.- Maydonga qiymat bermasdan
TS2564ni chaqiring, keyin uch xil usulda tuzating. - Metodni
forEachga to'g'ridan-to'g'ri berib, dasturni yiqiting. - Uni
this: Sinfparametri bilan kompilyatsiya vaqtida tutiladigan qiling.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.