Clase în TypeScript
TypeScript adaugă tipuri și modificatori de vizibilitate claselor din JavaScript.
Această pagină presupune că știi deja cum funcționează clasele obișnuite din JavaScript.
Membri: tipuri
Membrii unei clase — proprietățile și metodele ei — primesc tipuri prin adnotări de tip, la fel ca variabilele.
Exemplu
name: string declară o proprietate care trebuie să conțină text.
Person cu o proprietate name de tip string, creează o instanță și setează-i name la "Jane". Exemplul nu afișează nimic.
Ieșire: program TypeScript și rezultatul capturat
class Person {
name: string;
}
const person = new Person();
person.name = "Jane";
Membri: vizibilitate
Membrii unei clase pot avea și modificatori speciali care controlează de unde pot fi accesați.
Notă: În TypeScript există trei modificatori principali de vizibilitate.
public— (implicit) membrul poate fi accesat de oriundeprivate— membrul poate fi accesat doar din interiorul claseiprotected— membrul poate fi accesat din clasa însăși și din orice clasă care moștenește de la ea (vezi secțiunile despre moștenire de mai jos)
Notă: În interiorul unei clase, cuvântul cheie this se referă de obicei la instanța curentă a clasei.
Exemplu
Apelul getName() este permis pentru că metoda este publică. Citirea lui person.name din afara clasei este o eroare de compilare, pentru că name este privat.
private și public aplicați membrilor unei clase.
Declară o clasă Person cu un private name: string, un constructor public care îl setează și o metodă public getName(); creează un Person numit "Jane", afișează getName() (permis), apoi afișează direct person.name, astfel încât compilatorul să raporteze că name este privat și accesibil doar în interiorul clasei.
Ieșire: program TypeScript și rezultatul capturat
class Person {
private name: string;
public constructor(name: string) {
this.name = name;
}
public getName(): string {
return this.name;
}
}
const person = new Person("Jane");
console.log(person.getName()); // fără eroare
console.log(person.name); // Eroare: proprietatea „name” este privată și accesibilă doar în interiorul clasei „Person”.
Proprietăți din parametri
TypeScript oferă o scurtătură pentru definirea membrilor unei clase în constructor: adaugi un modificator de vizibilitate la parametrul constructorului, iar acesta devine automat membru.
Exemplu
private name: string din constructor declară membrul name și îi atribuie valoarea în același timp — nu mai este nevoie de o linie separată pentru proprietate.
Person al cărei constructor primește private name: string (cu corpul gol), plus o metodă public getName() care îl returnează; creează un Person numit "Jane" și afișează getName(), care tipărește Jane.
Ieșire: program TypeScript și rezultatul capturat
class Person {
// name este o variabilă membru privată
public constructor(private name: string) {}
public getName(): string {
return this.name;
}
}
const person = new Person("Jane");
console.log(person.getName());
Readonly
La fel ca la tablouri, cuvântul cheie readonly împiedică modificarea unui membru al clasei după ce acesta a fost setat.
Exemplu
Unui membru readonly trebuie să i se dea valoarea fie acolo unde este declarat, fie în constructor, iar apoi nu se mai poate schimba.
readonly aplicat unei proprietăți a clasei.
Declară o clasă Person cu un private readonly name: string setat o singură dată în constructor (cu un comentariu care explică faptul că nu se mai poate schimba ulterior) și o metodă public getName(); creează un Person numit "Jane" și afișează getName(), care tipărește Jane.
Ieșire: program TypeScript și rezultatul capturat
class Person {
private readonly name: string;
public constructor(name: string) {
// name nu mai poate fi schimbat după această definire inițială, care trebuie să fie fie la declarare, fie în constructor.
this.name = name;
}
public getName(): string {
return this.name;
}
}
const person = new Person("Jane");
console.log(person.getName());
Moștenire: Implements
O interfață poate descrie forma pe care trebuie să o respecte o clasă. Clasa promite că se potrivește cu ea prin cuvântul cheie implements.
Notă: O clasă poate implementa mai multe interfețe, enumerându-le după implements, separate prin virgulă, ca în class Rectangle implements Shape, Colored {
Exemplu
Rectangle trebuie să ofere o metodă getArea, pentru că interfața Shape cere una.
implements.
Declară o interfață Shape cu o proprietate de tip funcție getArea care returnează number, apoi o clasă Rectangle care o implementează folosind proprietățile din parametri protected readonly width și height și o metodă getArea() care returnează lățimea înmulțită cu înălțimea. Exemplul doar declară și nu afișează nimic.
Ieșire: program TypeScript și rezultatul capturat
interface Shape {
getArea: () => number;
}
class Rectangle implements Shape {
public constructor(protected readonly width: number, protected readonly height: number) {}
public getArea(): number {
return this.width * this.height;
}
}
Moștenire: Extends
O clasă poate porni de la o altă clasă folosind cuvântul cheie extends.
O clasă poate extinde o singură altă clasă.
Exemplu
Square extinde Rectangle, transmite aceeași valoare pentru lățime și înălțime către super și moștenește getArea fără să o mai scrie din nou.
extends.
Declară o interfață Shape și o clasă Rectangle care o implementează (width și height protected readonly, iar getArea() returnează produsul lor), apoi o clasă Square care extinde Rectangle, al cărei constructor primește un singur width și apelează super(width, width), moștenind getArea. Exemplul doar declară și nu afișează nimic.
Ieșire: program TypeScript și rezultatul capturat
interface Shape {
getArea: () => number;
}
class Rectangle implements Shape {
public constructor(protected readonly width: number, protected readonly height: number) {}
public getArea(): number {
return this.width * this.height;
}
}
class Square extends Rectangle {
public constructor(width: number) {
super(width, width);
}
// getArea este moștenită de la Rectangle
}
Override
Când o clasă extinde o alta, ea poate înlocui membrii părintelui care au același nume.
Versiunile mai noi de TypeScript îți permit să marchezi acest lucru explicit cu cuvântul cheie override.
Notă: În mod implicit, cuvântul cheie override este opțional atunci când suprascrii o metodă; el doar ajută la depistarea greșelilor, cum ar fi „suprascrierea” unei metode care nu există în părinte. Activează opțiunea noImplicitOverride pentru a-l face obligatoriu.
Exemplu
Square înlocuiește metoda toString moștenită de la Rectangle. Membrii protected rămân accesibili din Square.
override.
Declară o interfață Shape, o clasă Rectangle care o implementează cu width și height protected readonly, cu getArea() și un toString() care returnează "Rectangle[width=..., height=...]", apoi o subclasă Square al cărei override toString() returnează "Square[width=...]". Exemplul doar declară și nu afișează nimic.
Ieșire: program TypeScript și rezultatul capturat
interface Shape {
getArea: () => number;
}
class Rectangle implements Shape {
// folosirea lui protected pentru acești membri permite accesul din clasele care extind această clasă, cum ar fi Square
public constructor(protected readonly width: number, protected readonly height: number) {}
public getArea(): number {
return this.width * this.height;
}
public toString(): string {
return `Rectangle[width=${this.width}, height=${this.height}]`;
}
}
class Square extends Rectangle {
public constructor(width: number) {
super(width, width);
}
// acest toString înlocuiește metoda toString din Rectangle
public override toString(): string {
return `Square[width=${this.width}]`;
}
}
Clase abstracte
O clasă poate fi scrisă astfel încât să servească doar ca bază pentru alte clase, fără să implementeze toți membrii ei.
Acest lucru se face cu cuvântul cheie abstract pus pe clasă.
Membrii lăsați fără implementare folosesc și ei cuvântul cheie abstract.
Notă: O clasă abstractă nu poate fi instanțiată direct, pentru că nu toți membrii ei sunt implementați.
Exemplu
Polygon lasă getArea abstractă, dar implementează toString folosind-o. Rectangle extinde Polygon și oferă metoda getArea care lipsea.
abstract class Polygon cu o metodă public abstract getArea(): number și un toString() concret care returnează "Polygon[area=...]", apoi o clasă Rectangle care o extinde, cu width și height protected readonly, care apelează super() și implementează getArea(). Exemplul doar declară și nu afișează nimic.
Ieșire: program TypeScript și rezultatul capturat
abstract class Polygon {
public abstract getArea(): number;
public toString(): string {
return `Polygon[area=${this.getArea()}]`;
}
}
class Rectangle extends Polygon {
public constructor(protected readonly width: number, protected readonly height: number) {
super();
}
public getArea(): number {
return this.width * this.height;
}
}