"Bezpieczeństwo w Parku Jurajskim to kwestia najwyższej wagi," stwierdza stanowczo John Hammond, prezes InGen. "Niektóre dane i procedury muszą być dostępne dla wszystkich pracowników, inne tylko dla osób z odpowiednimi uprawnieniami, a jeszcze inne są tak krytyczne, że dostęp do nich ma wyłącznie najwyższe kierownictwo."
Podobnie jak w Parku Jurajskim, w programowaniu obiektowym kontrola dostępu do właściwości i metod klas jest fundamentalnym aspektem dobrego projektowania. TypeScript oferuje trzy modyfikatory dostępu, które pozwalają precyzyjnie określić, kto i w jakim zakresie może korzystać z poszczególnych elementów klas: public, private i protected.
Modyfikatory dostępu określają, z jakich poziomów kodu można uzyskać dostęp do właściwości i metod klasy:
Przyjrzyjmy się, jak te modyfikatory działają w praktyce, implementując system zarządzania dinozaurami w Parku Jurajskim.
Elementy oznaczone jako public są dostępne z dowolnego miejsca w kodzie - zarówno wewnątrz klasy, jak i na jej instancjach. Jest to domyślny modyfikator dostępu w TypeScript - jeśli nie określisz żadnego modyfikatora, element zostanie automatycznie oznaczony jako public.
1class Dinozaur {
2 // Właściwości publiczne
3 public nazwa: string;
4 public gatunek: string;
5 public wiek: number;
6
7 constructor(nazwa: string, gatunek: string, wiek: number) {
8 this.nazwa = nazwa;
9 this.gatunek = gatunek;
10 this.wiek = wiek;
11 }
12
13 // Metoda publiczna
14 public wyświetlInformacje(): void {
15 console.log(`${this.nazwa}: ${this.gatunek}, ${this.wiek} lat`);
16 }
17}
18
19// Tworzenie instancji
20const rex = new Dinozaur("Rex", "Tyrannosaurus", 7);
21
22// Dostęp do publicznych właściwości i metod z zewnątrz klasy
23console.log(rex.nazwa); // "Rex" - dostęp do publicznej właściwości
24rex.wiek = 8; // Modyfikacja publicznej właściwości
25rex.wyświetlInformacje(); // Wywołanie publicznej metodyWłaściwości i metody publiczne są jak ogólnodostępne informacje w parku - na przykład mapa parku, godziny otwarcia, czy lokalizacje toalet. Wszyscy mogą ich używać bez ograniczeń.
Elementy oznaczone jako private są dostępne tylko wewnątrz klasy, w której zostały zdefiniowane. Ta hermetyzacja pozwala na ukrycie wewnętrznych szczegółów implementacji i zapobiega przypadkowym modyfikacjom stanu z zewnątrz klasy.
1class DiagnozaZdrowia {
2 // Właściwości prywatne
3 private id: string;
4 private wynikiBadań: Record<string, number>;
5 private uwagi: string;
6 public statusZdrowia: "zdrowy" | "chory" | "krytyczny";
7
8 constructor(id: string) {
9 this.id = id;
10 this.wynikiBadań = {};
11 this.uwagi = "";
12 this.statusZdrowia = "zdrowy";
13 }
14
15 // Prywatna metoda - używana tylko wewnątrz klasy
16 private analizujWyniki(): "zdrowy" | "chory" | "krytyczny" {
17 // Złożona logika analizy wyników badań
18 const temperaturaCiała = this.wynikiBadań["temperaturaCiała"] || 37;
19 const poziomLeukocytów = this.wynikiBadań["poziomLeukocytów"] || 7000;
20
21 if (temperaturaCiała > 40 || poziomLeukocytów > 15000) {
22 return "krytyczny";
23 } else if (temperaturaCiała > 38.5 || poziomLeukocytów > 11000) {
24 return "chory";
25 } else {
26 return "zdrowy";
27 }
28 }
29
30 // Publiczne metody korzystające z prywatnych właściwości
31 public dodajWynikBadania(nazwa: string, wartość: number): void {
32 this.wynikiBadań[nazwa] = wartość;
33 this.statusZdrowia = this.analizujWyniki(); // Wywołanie prywatnej metody
34 }
35
36 public dodajUwagę(uwaga: string): void {
37 this.uwagi += uwaga + "\n";
38 }
39
40 public pobierzRaport(): string {
41 return `
42 ID: ${this.id}
43 Status zdrowia: ${this.statusZdrowia}
44 Uwagi: ${this.uwagi || "Brak"}
45 `;
46 }
47}
48
49// Tworzenie instancji
50const diagnozaRaptora = new DiagnozaZdrowia("VL-001");
51
52// Używanie publicznego API
53diagnozaRaptora.dodajWynikBadania("temperaturaCiała", 39.2);
54diagnozaRaptora.dodajWynikBadania("poziomLeukocytów", 12500);
55diagnozaRaptora.dodajUwagę("Objawy infekcji wirusowej");
56
57console.log(diagnozaRaptora.statusZdrowia); // "chory" - dostęp do publicznej właściwości
58console.log(diagnozaRaptora.pobierzRaport()); // Wywołanie publicznej metody
59
60// Próba dostępu do prywatnych elementów
61// console.log(diagnozaRaptora.id); // Błąd: Property 'id' is private
62// console.log(diagnozaRaptora.wynikiBadań); // Błąd: Property 'wynikiBadań' is private
63// diagnozaRaptora.analizujWyniki(); // Błąd: Property 'analizujWyniki' is privatePrywatne właściwości i metody są jak zastrzeżone procedury laboratorium genetycznego - tylko upoważniony personel laboratorium (metody klasy) ma do nich dostęp, a dla reszty personelu są one ukryte ze względów bezpieczeństwa.
Elementy oznaczone jako protected są dostępne wewnątrz klasy, w której zostały zdefiniowane, oraz w klasach dziedziczących. Pozwala to na tworzenie hierarchii klas, gdzie klasy pochodne mają dostęp do chronionych elementów klasy bazowej, ale elementy te pozostają niedostępne z zewnątrz hierarchii klas.
1// Klasa bazowa
2class Zwierzę {
3 // Właściwości chronione
4 protected id: string;
5 protected gatunek: string;
6 protected waga: number;
7 protected zdrowie: number; // 0-100
8
9 constructor(id: string, gatunek: string, waga: number) {
10 this.id = id;
11 this.gatunek = gatunek;
12 this.waga = waga;
13 this.zdrowie = 100;
14 }
15
16 // Chroniona metoda
17 protected zmodyfikujZdrowie(zmiana: number): void {
18 this.zdrowie = Math.max(0, Math.min(100, this.zdrowie + zmiana));
19 }
20
21 // Publiczna metoda
22 public wyświetlStatus(): string {
23 return `${this.gatunek} (${this.id}): Waga: ${this.waga}kg, Zdrowie: ${this.zdrowie}%`;
24 }
25}
26
27// Klasa dziedzicząca
28class Dinozaur extends Zwierzę {
29 public imię: string;
30 private poziomAgresji: number; // 0-10
31
32 constructor(id: string, gatunek: string, imię: string, waga: number) {
33 super(id, gatunek, waga);
34 this.imię = imię;
35 this.poziomAgresji = 5;
36 }
37
38 // Metoda wykorzystująca chronione elementy klasy bazowej
39 public nakarm(ilość: number): void {
40 this.zmodyfikujZdrowie(ilość * 5); // Dostęp do chronionej metody z klasy bazowej
41 this.poziomAgresji = Math.max(0, this.poziomAgresji - 1);
42 console.log(`${this.imię} został nakarmiony. Nowy poziom zdrowia: ${this.zdrowie}%`);
43 }
44
45 public doznajObrażeń(ilość: number): void {
46 this.zmodyfikujZdrowie(-ilość); // Dostęp do chronionej metody z klasy bazowej
47 this.poziomAgresji = Math.min(10, this.poziomAgresji + 2);
48 console.log(`${this.imię} doznał obrażeń. Nowy poziom zdrowia: ${this.zdrowie}%`);
49 }
50
51 // Nadpisanie metody bazowej z wykorzystaniem chronionych właściwości
52 public wyświetlStatus(): string {
53 return `${this.imię} (${this.gatunek}): Waga: ${this.waga}kg, Zdrowie: ${this.zdrowie}%, Agresja: ${this.poziomAgresji}/10`;
54 }
55}
56
57// Klasa dziedzicząca z modyfikacją chronionej właściwości
58class DinozaurMorski extends Zwierzę {
59 private głębokośćNurkowania: number;
60
61 constructor(id: string, gatunek: string, waga: number, głębokośćNurkowania: number) {
62 super(id, gatunek, waga);
63 this.głębokośćNurkowania = głębokośćNurkowania;
64
65 // Modyfikacja chronionej właściwości w konstruktorze
66 this.zdrowie = 90; // Morskie dinozaury zaczynają z mniejszym zdrowiem
67 }
68
69 public pływaj(czas: number): void {
70 // Używanie chronionej metody
71 this.zmodyfikujZdrowie(czas > 10 ? -10 : 5);
72
73 console.log(`Dinozaur morski ${this.id} pływał przez ${czas} minut na głębokości ${this.głębokośćNurkowania}m`);
74 console.log(`Nowy poziom zdrowia: ${this.zdrowie}%`);
75 }
76}
77
78// Tworzenie instancji
79const velociraptor = new Dinozaur("VL-002", "Velociraptor", "Blue", 150);
80const mosasaur = new DinozaurMorski("MS-001", "Mosasaurus", 15000, 50);
81
82// Używanie publicznych metod
83velociraptor.nakarm(2);
84velociraptor.doznajObrażeń(15);
85console.log(velociraptor.wyświetlStatus());
86
87mosasaur.pływaj(15);
88console.log(mosasaur.wyświetlStatus());
89
90// Próba dostępu do chronionych elementów
91// console.log(velociraptor.id); // Błąd: Property 'id' is protected
92// console.log(mosasaur.zdrowie); // Błąd: Property 'zdrowie' is protected
93// velociraptor.zmodyfikujZdrowie(50); // Błąd: Property 'zmodyfikujZdrowie' is protectedChronione właściwości i metody są jak procedury bezpieczeństwa parku - dostęp do nich mają tylko upoważnieni pracownicy i ich podwładni (klasa bazowa i klasy dziedziczące), ale nie goście parku (kod zewnętrzny).
TypeScript oferuje specjalną składnię dla konstruktorów, która pozwala na bezpośrednie deklarowanie właściwości z modyfikatorami dostępu w parametrach konstruktora. Jest to skrótowy zapis, który pozwala uniknąć powtarzania kodu.
1// Tradycyjny zapis
2class PracownikParku {
3 private id: string;
4 public imię: string;
5 public nazwisko: string;
6 protected poziomDostępu: number;
7
8 constructor(id: string, imię: string, nazwisko: string, poziomDostępu: number) {
9 this.id = id;
10 this.imię = imię;
11 this.nazwisko = nazwisko;
12 this.poziomDostępu = poziomDostępu;
13 }
14}
15
16// Skrócony zapis z modyfikatorami w parametrach konstruktora
17class PracownikParkuSkrócony {
18 constructor(
19 private id: string,
20 public imię: string,
21 public nazwisko: string,
22 protected poziomDostępu: number
23 ) {} // Puste ciało konstruktora - wszystko już zostało zainicjalizowane
24}
25
26// Oba zapisy działają identycznie
27const pracownik1 = new PracownikParku("EMP-001", "John", "Hammond", 10);
28const pracownik2 = new PracownikParkuSkrócony("EMP-002", "Ellie", "Sattler", 8);
29
30console.log(pracownik1.imię, pracownik1.nazwisko); // "John Hammond"
31console.log(pracownik2.imię, pracownik2.nazwisko); // "Ellie Sattler"
32
33// console.log(pracownik1.id); // Błąd: Property 'id' is private
34// console.log(pracownik2.id); // Błąd: Property 'id' is privateTa skrócona składnia jest szczególnie przydatna w prostych klasach z wieloma właściwościami, ponieważ redukuje ilość powtarzającego się kodu.
Jednym z głównych powodów stosowania modyfikatorów dostępu jest hermetyzacja - ukrywanie szczegółów implementacji i udostępnianie tylko kontrolowanego interfejsu do interakcji z klasą. Częścią tego podejścia jest stosowanie getterów i setterów - specjalnych metod kontrolujących dostęp do właściwości.
1class EnclosureSecurity {
2 // Prywatne właściwości
3 private _statusOgrodzenia: "aktywne" | "nieaktywne" | "w_naprawie";
4 private _poziomNaładowaniaBaterii: number; // 0-100
5 private _ostatniaPrzegląd: Date;
6 private _logZdarzeń: string[];
7
8 constructor() {
9 this._statusOgrodzenia = "aktywne";
10 this._poziomNaładowaniaBaterii = 100;
11 this._ostatniaPrzegląd = new Date();
12 this._logZdarzeń = ["System uruchomiony: " + new Date().toISOString()];
13 }
14
15 // Gettery - kontrolowany dostęp do odczytu prywatnych właściwości
16 get statusOgrodzenia(): "aktywne" | "nieaktywne" | "w_naprawie" {
17 this.dodajLog("Odczytano status ogrodzenia");
18 return this._statusOgrodzenia;
19 }
20
21 get poziomNaładowaniaBaterii(): number {
22 this.dodajLog("Odczytano poziom naładowania baterii");
23 return this._poziomNaładowaniaBaterii;
24 }
25
26 get ostatniaPrzegląd(): Date {
27 return new Date(this._ostatniaPrzegląd.getTime()); // Defensywna kopia
28 }
29
30 get raportBezpieczeństwa(): string {
31 this.dodajLog("Wygenerowano raport bezpieczeństwa");
32 return `
33 Status ogrodzenia: ${this._statusOgrodzenia}
34 Poziom naładowania baterii: ${this._poziomNaładowaniaBaterii}%
35 Ostatni przegląd: ${this._ostatniaPrzegląd.toLocaleDateString()}
36 Liczba zdarzeń w logu: ${this._logZdarzeń.length}
37 `;
38 }
39
40 // Settery - kontrolowany dostęp do modyfikacji prywatnych właściwości
41 set statusOgrodzenia(nowyStatus: "aktywne" | "nieaktywne" | "w_naprawie") {
42 this.dodajLog(`Zmieniono status ogrodzenia z ${this._statusOgrodzenia} na ${nowyStatus}`);
43 this._statusOgrodzenia = nowyStatus;
44
45 if (nowyStatus === "nieaktywne") {
46 this.uruchomProcedurySecurity();
47 }
48 }
49
50 // Ten setter zawiera logikę walidacyjną
51 set poziomNaładowaniaBaterii(nowyPoziom: number) {
52 if (nowyPoziom < 0 || nowyPoziom > 100) {
53 throw new Error("Poziom naładowania baterii musi być między 0 a 100");
54 }
55
56 const staraWartość = this._poziomNaładowaniaBaterii;
57 this._poziomNaładowaniaBaterii = nowyPoziom;
58 this.dodajLog(`Zmieniono poziom naładowania baterii z ${staraWartość}% na ${nowyPoziom}%`);
59
60 if (nowyPoziom < 20) {
61 this.dodajLog("UWAGA: Niski poziom baterii!");
62 }
63 }
64
65 // Prywatna metoda pomocnicza
66 private dodajLog(wiadomość: string): void {
67 this._logZdarzeń.push(`${new Date().toISOString()}: ${wiadomość}`);
68 }
69
70 // Prywatna metoda biznesowa
71 private uruchomProcedurySecurity(): void {
72 this.dodajLog("ALERT: Uruchomiono procedury awaryjne!");
73 // Logika obsługi sytuacji awaryjnej
74 }
75
76 // Publiczna metoda
77 public przeprowadźPrzegląd(): void {
78 this._ostatniaPrzegląd = new Date();
79 this.dodajLog("Przeprowadzono przegląd ogrodzenia");
80 this._poziomNaładowaniaBaterii = 100;
81 this._statusOgrodzenia = "aktywne";
82 }
83
84 // Publiczna metoda
85 public pobierzLogZdarzeń(): string[] {
86 // Zwracamy kopię, aby uniemożliwić modyfikację oryginalnego logu
87 return [...this._logZdarzeń];
88 }
89}
90
91// Użycie klasy
92const security = new EnclosureSecurity();
93
94// Używanie getterów
95console.log("Status ogrodzenia:", security.statusOgrodzenia);
96console.log("Poziom baterii:", security.poziomNaładowaniaBaterii);
97
98// Używanie setterów
99security.statusOgrodzenia = "w_naprawie";
100security.poziomNaładowaniaBaterii = 85;
101
102// Używanie publicznych metod
103security.przeprowadźPrzegląd();
104
105// Próba ustawienia nieprawidłowej wartości
106try {
107 security.poziomNaładowaniaBaterii = 110; // Wywoła błąd
108} catch (e) {
109 console.error(e.message);
110}
111
112// Odczyt raportu i logów
113console.log(security.raportBezpieczeństwa);
114console.log("Historia zdarzeń:");
115security.pobierzLogZdarzeń().forEach((log, i) => {
116 console.log(`${i + 1}. ${log}`);
117});Używanie getterów i setterów pozwala na większą kontrolę nad dostępem do danych:
Poniżej przedstawiamy kompleksowy przykład systemu zarządzania dinozaurami, który wykorzystuje wszystkie omówione modyfikatory dostępu dla stworzenia dobrze zorganizowanej architektury obiektowej:
1// Typy i interfejsy
2type StatusDinozaura = "zdrowy" | "chory" | "w leczeniu" | "uśpiony" | "zmarły";
3type TypDiety = "mięsożerny" | "roślinożerny" | "wszystkożerny";
4
5interface IMonitorowania {
6 rozpocznijMonitorowanie(): void;
7 zakończMonitorowanie(): void;
8 pobierzStatusMonitorowania(): string;
9}
10
11// Abstrakcyjna klasa bazowa
12abstract class ZwierzęParku {
13 // Właściwości z różnymi modyfikatorami dostępu
14 private _id: string;
15 protected _gatunek: string;
16 protected _wiek: number;
17 protected _waga: number;
18 protected _status: StatusDinozaura;
19 private _dataUtworzenia: Date;
20 private _ostatniaAktualizacja: Date;
21
22 constructor(id: string, gatunek: string, wiek: number, waga: number) {
23 this._id = id;
24 this._gatunek = gatunek;
25 this._wiek = wiek;
26 this._waga = waga;
27 this._status = "zdrowy";
28 this._dataUtworzenia = new Date();
29 this._ostatniaAktualizacja = new Date();
30 }
31
32 // Gettery
33 get id(): string {
34 return this._id;
35 }
36
37 get gatunek(): string {
38 return this._gatunek;
39 }
40
41 get wiek(): number {
42 return this._wiek;
43 }
44
45 get waga(): number {
46 return this._waga;
47 }
48
49 get status(): StatusDinozaura {
50 return this._status;
51 }
52
53 // Setter ze sprawdzeniem wartości i aktualizacją daty
54 set status(nowyStatus: StatusDinozaura) {
55 if (this._status !== nowyStatus) {
56 this._status = nowyStatus;
57 this._ostatniaAktualizacja = new Date();
58 this.logZmianyStatusu(nowyStatus);
59 }
60 }
61
62 // Chroniona metoda dostępna dla klas dziedziczących
63 protected aktualizujWagę(nowaWaga: number): void {
64 if (nowaWaga > 0) {
65 this._waga = nowaWaga;
66 this._ostatniaAktualizacja = new Date();
67 } else {
68 throw new Error("Waga musi być większa od zera.");
69 }
70 }
71
72 // Prywatna metoda dostępna tylko wewnątrz tej klasy
73 private logZmianyStatusu(nowyStatus: StatusDinozaura): void {
74 console.log(`[${new Date().toISOString()}] Zmiana statusu ${this._id}: ${nowyStatus}`);
75 }
76
77 // Abstrakcyjna metoda - każda klasa dziedzicząca musi ją zaimplementować
78 abstract pobierzOpisKliniczny(): string;
79
80 // Publiczna metoda
81 public pobierzPodstawoweDane(): string {
82 return `ID: ${this._id} | Gatunek: ${this._gatunek} | Wiek: ${this._wiek} lat | Waga: ${this._waga} kg | Status: ${this._status}`;
83 }
84}
85
86// Klasa dziedzicząca
87class Dinozaur extends ZwierzęParku implements IMonitorowania {
88 // Prywatne właściwości specyficzne dla dinozaurów
89 private _dieta: TypDiety;
90 private _poziomAgresji: number; // 1-10
91 private _czyMonitorowany: boolean;
92 private _ostatniPosiłek: Date | null;
93 private _przypisanyWybieg: string | null;
94
95 constructor(
96 id: string,
97 gatunek: string,
98 wiek: number,
99 waga: number,
100 dieta: TypDiety,
101 poziomAgresji: number
102 ) {
103 super(id, gatunek, wiek, waga);
104 this._dieta = dieta;
105 this._poziomAgresji = this.walidujPoziomAgresji(poziomAgresji);
106 this._czyMonitorowany = false;
107 this._ostatniPosiłek = null;
108 this._przypisanyWybieg = null;
109 }
110
111 // Implementacja metody abstrakcyjnej
112 pobierzOpisKliniczny(): string {
113 let opis = `Dinozaur ${this.gatunek} (ID: ${this.id})\n`;
114 opis += `Status zdrowotny: ${this.status}\n`;
115 opis += `Wiek: ${this.wiek} lat, Waga: ${this.waga} kg\n`;
116 opis += `Dieta: ${this._dieta}\n`;
117 opis += `Poziom agresji: ${this._poziomAgresji}/10\n`;
118 opis += `Ostatni posiłek: ${this._ostatniPosiłek ? this._ostatniPosiłek.toLocaleString() : "Brak danych"}\n`;
119
120 return opis;
121 }
122
123 // Implementacja interfejsu IMonitorowania
124 rozpocznijMonitorowanie(): void {
125 this._czyMonitorowany = true;
126 console.log(`Rozpoczęto monitorowanie dinozaura ${this.id}`);
127 }
128
129 zakończMonitorowanie(): void {
130 this._czyMonitorowany = false;
131 console.log(`Zakończono monitorowanie dinozaura ${this.id}`);
132 }
133
134 pobierzStatusMonitorowania(): string {
135 return this._czyMonitorowany ? "Aktywny" : "Nieaktywny";
136 }
137
138 // Publiczne metody specyficzne dla dinozaurów
139 public nakarm(ilość: number): void {
140 if (ilość <= 0) {
141 throw new Error("Ilość pokarmu musi być większa od zera.");
142 }
143
144 const przyrostWagi = this._dieta === "mięsożerny" ? ilość * 0.3 : ilość * 0.2;
145 this.aktualizujWagę(this.waga + przyrostWagi);
146
147 this._ostatniPosiłek = new Date();
148 this._poziomAgresji = this.walidujPoziomAgresji(this._poziomAgresji - 1);
149
150 console.log(`Dinozaur ${this.id} został nakarmiony. Nowa waga: ${this.waga} kg`);
151 }
152
153 public przydzielDoWybiegu(kodWybiegu: string): void {
154 this._przypisanyWybieg = kodWybiegu;
155 console.log(`Dinozaur ${this.id} został przydzielony do wybiegu ${kodWybiegu}`);
156 }
157
158 public uśpij(): void {
159 this.status = "uśpiony";
160 this._poziomAgresji = 1;
161 console.log(`Dinozaur ${this.id} został uśpiony`);
162 }
163
164 public obudź(): void {
165 if (this.status === "uśpiony") {
166 this.status = "zdrowy";
167 this._poziomAgresji = this.walidujPoziomAgresji(this._poziomAgresji + 2);
168 console.log(`Dinozaur ${this.id} został obudzony`);
169 }
170 }
171
172 // Gettery i settery
173 get dieta(): TypDiety {
174 return this._dieta;
175 }
176
177 get poziomAgresji(): number {
178 return this._poziomAgresji;
179 }
180
181 get ostatniPosiłek(): Date | null {
182 return this._ostatniPosiłek ? new Date(this._ostatniPosiłek.getTime()) : null;
183 }
184
185 get przypisanyWybieg(): string | null {
186 return this._przypisanyWybieg;
187 }
188
189 set poziomAgresji(poziom: number) {
190 this._poziomAgresji = this.walidujPoziomAgresji(poziom);
191 }
192
193 // Prywatna metoda pomocnicza
194 private walidujPoziomAgresji(poziom: number): number {
195 return Math.max(1, Math.min(10, poziom));
196 }
197}
198
199// Użycie systemu
200function testSystemuZarządzaniaDinozaurami() {
201 // Tworzenie dinozaurów
202 const trex = new Dinozaur("T-REX-01", "Tyrannosaurus Rex", 8, 7500, "mięsożerny", 9);
203 const stegozaur = new Dinozaur("STEG-01", "Stegosaurus", 12, 5000, "roślinożerny", 4);
204
205 // Wyświetlanie podstawowych informacji
206 console.log("=== DANE PODSTAWOWE ===");
207 console.log(trex.pobierzPodstawoweDane());
208 console.log(stegozaur.pobierzPodstawoweDane());
209
210 // Operacje na dinozaurach
211 trex.nakarm(50);
212 trex.przydzielDoWybiegu("CARNIVORE-A");
213 trex.rozpocznijMonitorowanie();
214
215 stegozaur.nakarm(80);
216 stegozaur.przydzielDoWybiegu("HERBIVORE-B");
217
218 // Zmiana statusu
219 trex.status = "w leczeniu";
220 stegozaur.uśpij();
221
222 // Pobieranie raportów klinicznych
223 console.log("\n=== RAPORTY KLINICZNE ===");
224 console.log(trex.pobierzOpisKliniczny());
225 console.log(stegozaur.pobierzOpisKliniczny());
226
227 // Status monitorowania
228 console.log("\n=== STATUS MONITOROWANIA ===");
229 console.log(`T-Rex monitoring: ${trex.pobierzStatusMonitorowania()}`);
230 console.log(`Stegozaur monitoring: ${stegozaur.pobierzStatusMonitorowania()}`);
231
232 // Próba dostępu do prywatnych/chronionych elementów
233 // Poniższe linie spowodowałyby błąd kompilacji:
234 // console.log(trex._id); // Błąd: Property '_id' is private
235 // console.log(trex._gatunek); // Błąd: Property '_gatunek' is protected
236 // trex.logZmianyStatusu("zdrowy"); // Błąd: Property 'logZmianyStatusu' is private
237 // trex.walidujPoziomAgresji(5); // Błąd: Property 'walidujPoziomAgresji' is private
238}
239
240// Uruchomienie testu
241testSystemuZarządzaniaDinozaurami();W powyższym przykładzie:
Wybór odpowiedniego modyfikatora dostępu zależy od konkretnego przypadku użycia, ale istnieje kilka ogólnych zasad:
Używaj private dla:
Używaj protected dla:
Używaj public dla:
Modyfikatory dostępu w TypeScript są kluczowym narzędziem do implementacji zasad dobrego projektowania obiektowego, takich jak enkapsulacja, dziedziczenie i polimorfizm. Pozwalają na precyzyjną kontrolę dostępu do właściwości i metod klas, co sprzyja tworzeniu bezpiecznego, modularnego i łatwego w utrzymaniu kodu.
Podobnie jak w Parku Jurajskim, gdzie system bezpieczeństwa wymaga różnych poziomów dostępu, dobrze zaprojektowany system obiektowy wykorzystuje modyfikatory dostępu, aby zapewnić, że każdy element jest dostępny tylko dla tych, którzy rzeczywiście powinni mieć do niego dostęp.
John Hammond podsumowałby to krótko: "W Parku Jurajskim i w programowaniu - bezpieczeństwo jest najważniejsze. Modyfikatory dostępu są jak strefy bezpieczeństwa w parku - publiczne dla wszystkich, chronione dla specjalistów, a prywatne tylko dla najwyższego szczebla zarządzania. To klucz do utrzymania porządku i zapobiegania... niespodziankom."