PO Typy uogólnione: Różnice pomiędzy wersjami
Nie podano opisu zmian |
Nie podano opisu zmian |
||
Linia 54: | Linia 54: | ||
private EltStosu wierzch; | private EltStosu wierzch; | ||
public Stos() { | public Stos() { | ||
wierzch = null; | wierzch = null; |
Wersja z 01:42, 6 sie 2006
(moduł w trakcie pisania)
(wymagania wstępne:
reguła podstawiania (dziedziczenie) typy referencyjne
)
Typy uogólnione
Wprowadzenie
Siłą programowania obiektowego jest łatwość opisywania w nim i tworzenia abstrakcji. Pojęcie klasy pozwala tworzyć abstrakcje, zaś mechanizm dziedziczenia ułatwia tworzenie nowych abstrakcji na podstawie już istniejących.
Czasami jednak okazuje się, że te narzędzia nie zaspokajają jeszcze wszystkich naszych potrzeb. Niejednokrotnie tworzymy pojęcia, które chcielibyśmy nie tylko sparametryzować występującymi w nich wartościami (co czynimy wprowadzając do klas atrybuty), czy czynnościami (co pozwalają nam osiągnąć metody), lecz także typami obiektów przechowywanych lub przetwarzanych przez klasy.
Na pierwszy rzut oka może się wydawać, że sam fakt dysponowania mechanizmem dziedziczenia i regułą podstawiania pozwala na abstrahowanie do typu przetwarzanych obiektów. Rzeczywiście możemy zadeklarować, że dane przechowywane w naszej klasie są typu Object i dzięki regule podstawiania umieszczać w tak zedeklarowanych atrybutach wartości dowolnego typu referencyjnego <ref name="PO_slaba_Java"> Ze względu na specyfikę Javy musimy ograniczyć się tu tylko do typów referencyjnych, także rozwiązanie przyjęte w Javie - które dalej omawiamy - ma tę niedogodność.</ref> Zobaczmy dlaczego takie rozwiązanie jest niedobre na przykładzie fragmentu deklaracji klasy Stos. Chcemy mieć tradycyjny stos przechowujący wartości dowolnego typu referencyjnego. Możemy w tym celu stworzyć listę elementów stosu. Elementy Stosu zapamiętamy w obiektach klasy EltStosu, zaś sam obiekt klasy Stos będzie pamietał jedynie pierwszy element listy.
Oto przykładowa implementacja (z pominiętymi mniej istotnymi elementami).
public class Stos { private EltStosu wierzch; public Stos() { wierzch = null; } public boolean pusty(){return wierzch == null;} public void wstaw(Object elt){ wierzch = new EltStosu(elt, wierzch);} public Object pobierz() throws PustyStos { if (pusty()) throw new PustyStos(); Object wynik = wierzch.elt; wierzch = wierzch.nast; return wynik; } }
class EltStosu { public final Object elt; public final EltStosu nast; // Ponieważ obiekty klasy EltStosu są ukryte w Stosie, nie // ma potrzeby deklarowania ich atrybutów jako prywatnych. // Ponadto deklaracja final daje tu zwiększone bezpieczeństwo. /** Creates a new instance of EltStosu */ public EltStosu(Object elt, EltStosu nast) { this.elt = elt; this.nast = nast; } }
class PustyStos extends Exception{}
Klasy parametryzowane typami
Metody parametryzowane typami
Ograniczenia typów uogólnionych w Javie
<references/>