public, private, protected în TypeScript

Clase TypeScript 1.3

Modificatorii de acces spun cine poate folosi un câmp sau o metodă: oricine, doar clasa sau și clasele derivate.

Sintaxă
class A {
    public x: number;      // implicit: vizibil peste tot
    private y: number;     // doar în clasa A
    protected z: number;   // în A și în clasele derivate
}

Ce face public, private, protected

public este implicit: membrul poate fi folosit de oriunde. private permite folosirea doar în interiorul clasei. protected permite folosirea în clasă și în clasele care o extind, dar nu din exterior.

Acești modificatori sunt verificați doar la compilare. În JavaScript-ul generat, un câmp private este o proprietate obișnuită, pe care o poate citi oricine (de exemplu cu console.log sau JSON.stringify). TypeScript lasă chiar și o portiță: obiect["camp"] ocolește verificarea. Pentru câmpuri cu adevărat private la rulare există #câmpuri din JavaScript.

Modificatorii se pot pune și pe constructor (private constructor interzice new din afară, util pentru metode de tip „fabrică”) și pe parametrii constructorului (vezi parameter properties).

Exemple

Exemplul 1: Cele trei niveluri de acces

class Angajat {
    public nume: string;
    protected salariu: number;
    private cnp: string;

    constructor(nume: string, salariu: number, cnp: string) {
        this.nume = nume;
        this.salariu = salariu;
        this.cnp = cnp;
    }

    private ascunde(): string {
        return this.cnp.slice(0, 1) + "*".repeat(this.cnp.length - 1);
    }

    fisa(): string {
        return `${this.nume} (CNP ${this.ascunde()})`;
    }
}

class Manager extends Angajat {
    bonus(): number {
        return this.salariu * 0.1;   // protected: permis în clasa derivată
    }
}

const m = new Manager("Ana", 9000, "2950101123456");
console.log(m.fisa(), m.bonus());

Rezultat

Ana (CNP 2************) 900

Exemplul 2: Acces interzis din afara clasei

class Cont {
    private sold = 100;
    protected moneda = "lei";
}
const c = new Cont();
console.log(c.sold, c.moneda);

Eroarea afișată de tsc

exemplu.mts(6,15): error TS2341: Property 'sold' is private and only accessible within class 'Cont'.
exemplu.mts(6,23): error TS2445: Property 'moneda' is protected and only accessible within class 'Cont' and its subclasses.

Exemplul 3: private nu ascunde nimic la rulare

Câmpul sold apare în console.log și în JSON. Accesul cu paranteze pătrate nu este verificat de tsc.

class Cont {
    private sold = 100;
    depune(suma: number) {
        this.sold += suma;
    }
}

const c = new Cont();
c.depune(50);
console.log(c, JSON.stringify(c));
console.log(c["sold"]);

Rezultat

Cont { sold: 150 } {"sold":150}
150

Greșeli frecvente

  • Te bazezi pe private pentru securitate. Este o regulă pentru programatori, nu o protecție la rulare; folosește #camp.
  • Faci totul private și apoi adaugi getter-e pentru fiecare câmp. Ascunde doar ce chiar nu trebuie atins din afară.

Comenzi înrudite

  • #câmpuri private: Câmpurile care încep cu # sunt private și la rulare: nu pot fi citite deloc din afara clasei.
  • class: Clasele din JavaScript, cu tipuri pe câmpuri, constructor și metode, plus modificatori de acces și interfețe.
  • constructor parameter properties: Un modificator pus pe un parametru al constructorului declară câmpul și îl inițializează automat.
  • readonly: Marchează o proprietate care primește valoare o singură dată și nu mai poate fi modificată după aceea.
  • extends: O clasă moștenește câmpurile și metodele altei clase; o interfață preia proprietățile altor interfețe.