BETA
Aby się zalogować, najpiew wybierz portal.
Aby się zarejestrować, najpiew wybierz portal.
Podaj słowa kluczowe
Słowa kluczowe muszą mieć co najmniej 3 sąsiadujące znaki alfanumeryczne
Pole zawiera niedozwolone znaki

Baza wiedzy











Wprowadzenie do programowania w TypeScript: współpraca klas i interfejsów oraz dziedziczenie

04-06-2014 11:00 | Krzysztof Pruszyński
W tym artykule nauczysz się łączyć ze sobą zalety, które oferuje wspólne użycie klas i interfejsów oraz dowiesz się jak zachowują się poszczególne elementy podczas dziedziczenia w TypeScript.

Autor: Krzysztof Pruszyński

Bardzo ważnym elementem w programowaniu obiektowym jest dziedziczenie. Dzięki niemu możemy tworzyć typy ogólne, które wykorzystujemy, aby uszczegółowić dziedziczącą klasę. Pisząc program i używając osobno klas i interfejsów pozbawiamy się bardzo dobrego i potężnego narzędzia w obiektowym programowaniu. W poprzednich artykułach tak właśnie to wyglądało, jednak w dzisiejszym dowiemy się, jak wygląda współpraca klas i interfejsów oraz jak działa dziedziczenie w TypeScript.

 

Przed rozpoczęciem lektury artykułu powinniśmy zapoznać się z poprzednimi dwoma wpisami z serii - image
Rys. 1 Brak implementacji interfejsu w klasie

 

Oznacza to, że konstrukcja, jaką zawiera w sobie interfejs nie została jeszcze zaimplementowana w klasie.

5.    Zamień zatem poprzedni konstruktor na taki fragment kodu:

constructor(public wiek : number, public nazwa: string, public rasa: string) { }

6.    Oraz zaimplementuj ciało metody podajWiek, wstawiając ją na koniec klasy:

podajWiek() {

        alert("Wiek tego zwierzaka to: " + this.wiek);

    }

 

W tym momencie otrzymujemy w pełni zaimplementowaną współpracę pomiędzy klasą, a interfejsem. Klasa w konstruktorze zawiera właściwość wiek oraz implementację metody podajWiek. Możemy wtedy stworzyć obiekt Pies.

7.    Na końcu pliku napisz:

var pies = new Pies(5,"Ciapek","York");

alert(pies.pokazInformacje());

 

W ten sposób stworzyliśmy instancję klasy Pies, gdzie mamy dostęp do jej właściwości oraz metod. Nic nie stoi na przeszkodzie aby stworzyć kolejną klasę, która implementuje ten sam interfejs. Po to właśnie go stworzyliśmy i taka jest jego główna rola.

8.    Napisz:

class Kot implements IZwierze {

    constructor(public wiek: number, public nazwa: string) {

    }

 

    podajWiek() {

        alert("Wiek tego zwierzaka to: " + this.wiek);

    }

}

 

var kot = new Kot(5,"Filemon");

kot.podajWiek();

 

Implementacja jest bardzo podobna, jednak w przypadku Psa wzbogacona o własne, szczegółowe metody i właściwości. Pokazuje to nam, że możemy tworzyć uniwersalne interfejsy, które ułatwią nam tworzenie klas, które muszą posiadać wymagane elementy.

Dzięki takiemu podejściu otrzymujemy prostszy i bardziej intuicyjny kod, który różni się dosyć mocno od wygenerowanego pliku JavaScriptu.

Dziedziczenie w TypeScript

W JavaScript każda funkcja, która występuje w roli klasy (konstruktora) posiada swój prototyp, który domyślnie jest pusty i posiada go każdy obiekt. Dzięki jego użyciu możemy stworzyć coś na kształt dziedziczenia dostępnego w innych językach zorientowanych obiektowo. W przypadku TypeScript wygląda to inaczej.

Informacja

Przykładowy kod JavaScript:

function piesHodowlany(nazwa,rasa,przydomekHodowlany){

Pies.call(this,nazwa,rasa);

this.przydomekHodowlany = przydomekHodowlany;

}

piesHodowlany.prototype= Object.create(Pies.prototype);

 

W przypadku konstruktora piesHodowlany wywołujemy metodę CALL, która odpowiada za udostępnienie pól konstruktora Pies. Następnie przekazujemy prototyp konstruktora bazowego dla funkcji piesHodowlany. W tym miejscu właśnie następuje dziedziczenie w JavaScript. Jest to wielce różne od tego, co oferuje np. język C#, jednak nie martwmy się, jeżeli tego nie rozumiemy ponieważ w tym artykule poznamy bardziej przyjazne podejście, które oferuje TypeScript.

 

1.     Na końcu stworzonego wcześniej pliku napisz:

class PiesHodowlany extends Pies {

    constructor(nazwa: string, rasa: string, public positon: string) {}

}

Stworzyliśmy klasę PiesHodowlany, która dziedziczy po klasie bazowej Pies. Pierwsze, co rzuca się w oczy to słówko kluczowe CLASS. Następnym elementem jest napisanie konstruktora naszej klasy, jednak nasza linijka kodu zostaje podkreślona przez kompilator, a gdy na nią najedziemy to pojawia się taki oto komunikat (Rys. 2 Błąd kompilatora mówiący o braku użycia metody „super”):

 

image
Rys. 2 Błąd kompilatora mówiący o braku użycia metody „super”

Potrzebujemy wywołania konstruktora klasy bazowej, a żeby to zrobić musimy użyć wywołania metody SUPER w tym miejscu:

class PiesHodowlany extends Pies {

    constructor(nazwa: string, rasa: string, public positon: string) {

        super(wiek, nazwa, rasa);

    }

}

 

Dzięki takiemu podejściu możemy intuicyjnie dziedziczyć po klasach nadrzędnych, nie zagłębiając się w często skomplikowaną strukturę, jaką tworzy w tym czasie wygenerowany kod JavaScriptu. Gdy już mamy taki kod, chcielibyśmy wykorzystać właściwości oraz metody z klasy bazowej. Niestety, w obecnej wersji TypeScript wygląda to w ten sposób, że musimy przesłonić elementy klasy Pies nową implementacją tak, jak w przypadku przesłaniania metod w klasie lub funkcji.

Podsumowanie

W tym artykule dowiedzieliśmy się,jakie są różnice w dziedziczeniu pomiędzy TypeScript, a JavaScript. Niestety, TS nie rozwiązuje tej cechy tak dobrze jak powinien. Na pewno zmieni się to w dalszych wydaniach języka. Zobaczyliśmy tu również jakie możliwości drzemią w uzupełnianiu się interfejsów i klas. W następnym, i ostatnim już artykule z tego cyklu, dowiemy się czym są moduły i jak one działają.

Komentarze 0

pkt.

Zaloguj się lub Zarejestruj się aby wykonać tę czynność.