od Podstaw
1 godz. 54 min · Typescript · Full-stack i Programowanie
Adam GospodarczykZacznijmy od tego, że JavaScript jest dynamicznie typowany. Oznacza to, że typy zmiennych mogą się zmieniać w czasie wykonywania programu, a my nie mamy nad nimi kontroli. A po co nam ta kontrola? Między innymi po to, aby przypadkowo nie dodać typu number do string lub przekazać do funkcji nieprawidłowe danych. Ogromną zaletą jest to, że o tego typu błędach dowiadujemy się już na etapie pisania kodu a nie dopiero w trakcie jego wykonywania... na produkcji.
Prawdopodobnie znasz mechanizm intellisense, czyli inteligentnego podpowiadania kodu przez edytor. Pisząc kod w TypeScript, tworzysz definicje typów dotyczących Twojej aplikacji. W ten sposób dostęp do definicji klas i właściwości obiektów masz właściwie na wyciągnięcie myszki. Wystarczy "hover" na funkcji aby uzyskać szczegółowe informacje, które pomogą Ci w pisaniu kodu. Oprócz tego otrzymasz również automatyczne podpowiedzi w trakcie dostępu do właściwości i metod. Nic tylko pisać kod!
Nie musisz przepisywać całego projektu. TypeScript stanowi nadzbiór JavaScriptu. Zatem cały Twój projekt jest z nim w 100% kompatybilny, a Ty możesz stopniowo dodawać definicje typów. Nawet nie będziesz wiedział kiedy typy pojawią się w całej Twojej aplikacji. To daje Ci również możliwość uczenia się TypeScriptu w trakcie jego wdrażania. W tym kursie opanujesz podstawy a później... sam zobaczysz!
Ten kurs został stworzony z myślą o programistach, którzy podstawy JavaScriptu mają już za sobą i chcą poznać zalety statycznego typowania oferowanego przez TypeScript. Na początku Kursu zaczynamy również od krótkiej powtórki najważniejszych elementów samego JS.
3.8+
Niewątpliwie nieodłącznym elementem klas
oraz programowania obiektowego jest tak zwane dziedziczenie. Na czym dokładnie to
dziedziczenie polega i w jaki sposób odbywa się w TypeScripcie
opowiem Ci właśnie w tej lekcji.
Mamy tutaj naszą klasę movie, do której dodamy teraz kilka nowych właściwości.
Będą to konkretnie gatunek oraz czas trwania. No i oczywiście chciałbym również,
żeby informacja o tym ile tego filmu obejrzałem również była zapamiętywana.
Aby to osiągnąć tworzę nową właściwość i metodę play.
Oczywiście jej implementacja w tej chwili służy wyłącznie przykładowi.
Tak czy inaczej nasza klasa jest w tym
momencie gotowa do wykorzystania. Do konstruktora oprócz tytułu
muszę teraz przekazać gatunek oraz czas trwania.
Tak przygotowany film nie tylko mogę włączyć, ale również mogę zapamiętać
informację o tym, w którym miejscu skończyłem oglądanie.
Teoretycznie na ten moment mam wszystko czego mi trzeba.
Ale wyobraźmy sobie, że chciałbym teraz posłuchać muzyki. No to tworzę nową klasę
Song, która w zasadzie będzie miała takie same właściwości jak klasa movie,
a w dodatku będzie również posiadać właściwość Progress oraz metodę Play.
Czy widzisz teraz jakieś podobieństwa pomiędzy klasą movie oraz klasą song?
W zasadzie w tej chwili są dokładnie takie
same, ale nie mogę wykorzystać klasy movie do odtwarzania utworów i odwrotnie.
W końcu pomiędzy nimi będą występować pewne różnice.
Ale mogę teraz utworzyć nową klasę Media,
która będzie posiadać te wszystkie cechy wspólne.
Pozwolę sobie teraz wykorzystać magię kina,
aby po prostu utworzyć tą klasę. Przepisałem tutaj całą zawartość naszych klas.
Zauważ jednak, że pojawiło się tutaj dodatkowe pole Type, które będzie
przechowywać informacje o tym czy mówimy o utworze czy o filmie.
Tak czy inaczej teraz cała logika z klasy
movie oraz z klasy Song nie jest nam już potrzebna.
Jednak w dalszym ciągu musimy zadbać o przekazanie informacji, które mamy tutaj.
One trafiają bezpośrednio do naszych klas a konkretnie do ich konstruktorów.
Dlatego teraz zarówno klasa movie, jaki Song będzie posiadała konstruktor, którego
zadaniem będzie w jakiś sposób przekazanie tych wszystkich informacji do klasy
nadrzędnej media. I aby to zrobić musimy przede wszystkim
zasygnalizować, że klasa movie dziedziczy po klasie media i robimy to słowem kluczowym
Extends. Następnie, aby przekazać informacje z tego konstruktora
do tego, musimy po prostu wywołać ten konstruktor. Wewnątrz klasy podrzędnej
możemy to zrobić korzystając z metody
super. Przekazujemy do niej informacje z konstruktora klasy movie oraz dodatkowo
musimy pamiętać tutaj o właściwości type.
I teraz to samo powtarzam w przypadku klasy song.
Efekt końcowy jaki tutaj mamy jest dokładnie taki sam z tą różnicą, że w tym
miejscu nie mamy powtórzenia całej logiki, która jest nam potrzebna.
No i oczywiście tutaj zamiast movie jest Song. Jeszcze teraz na koniec utwórzmy
nowy obiekt na podstawie klasy Song i dzięki temu będziemy mogli odczytać
zarówno jego typ, jak i po prostu odtworzyć ten utwór. Ponownie
wszystko działa tutaj dokładnie tak jak wcześniej.
Czyli podsumowując: mamy tutaj do
czynienia z dziedziczeniem, które sygnalizujemy słowem kluczowym Extends.
Dodatkowo, aby wykonać konstruktor klasy
nadrzędnej wykorzystujemy metodę super. Swoją drogą z tej metody będziemy
korzystać jeszcze niejednokrotnie. Zanim zakończymy tę lekcję
muszę powiedzieć jeszcze o jednej ważnej rzeczy. Mianowicie pomimo tego, że
dziedziczenie było z nami przez bardzo długi czas, tak obecnie zdecydowanie lepiej
korzystać z kompozycji zamiast dziedziczenia.
Więcej informacji na ten temat znajdziesz pod hasłem composition over inheritance.
Nie zmienia to jednak faktu, że zasady dziedziczenia zdecydowanie musisz znać.
Tymczasem w tej lekcji to już wszystko i słyszymy się za chwilę.
Klasa Movie · 1 min
class Movie {
constructor(public name: string, public genre: string, public duration: number) {}
}Klasa Media · 2 min
class Media {
public progress = 0
constructor(
readonly name: string,
public readonly type: string,
public readonly genre: string,
public readonly duration: number,
) {}
play() {
this.progress += 1
}
}Klasy Song i Movie · 3 min
class Movie extends Media {
constructor(name: string, genre: string, duration: number) {
super(name, "movie", genre, duration)
}
}
class Song extends Media {
constructor(name: string, genre: string, duration: number) {
super(name, "song", genre, duration)
}
}Obiekty Song i Movie · 3 min
const bestMovieEver = new Movie("Peaceful Warior", "Drama", 7200)
bestMovieEver.play()
bestMovieEver.progress /*?*/
const bestSongEver = new Song("Heart of Courage", "Cinematic", 117)
bestSongEver.type /*?*/
bestSongEver.play()
bestSongEver.progress /*?*/