Implementace seznamu pomocí OOP

Chceme vytvořit abstraktní datový typ seznam. Naše implementace má mít tu vlastnost, že v každém okamžiku zachovává uspořádání prvků seznamu. To zajistí metoda vlož, která zatřídí prvek na správné místo seznamu. Dále chceme s minimem dalšího programování vytvářet nové typy seznamů, pro další typy hodnot, které do seznamu vkládáme. Zde budeme uvažovat pouze typy integer a string.

V každé z následujících variant je seznam reprezentován třídou, tedy pro použití seznamu musíme vytvořit její instanci. Potom můžeme vytvářet libovolné možství různých seznamů (instancí).

Vlastní seznam bude tvořen záznamy:

type ukpol = ^pol;
     pol = record
             dal: ukpol;
	     hod: typ_hodnoty;
	   end;
Od každého seznamu vyžadujeme následujicí metody:
constructor init
inicializace na prázdný seznam
procedure vlož(x:typ_hodnoty)
vloží prvek (daný jako parametr) do seznamu
function odeber(n:integer):typ_hodnoty
odebere n-tý prvek ze seznamu
procedure vypiš
vypíše seznam na standardní výstup

Varianta I.

Máme hierarchii tříd seznamů -- pro každý typ vkládané hodnoty jedna třída. V naše případě máme tedy dvě třídy: seznam_int a seznam_string. Typ_hodnoty bude poiter. V základní třídě seznam_int definujeme další dvě metody, které nám zajistí znovupoužitelnost ostatních metod, bez jejich předefinování.
procedure vypiš_prvek(x:pointer)
vypíše na standardní výstup hodnotu jednoho prvku, zadaného jako parametr

Tato metoda je použita v metodě vypiš. Ve svém těle přetypuje parametr x a vypíše jeho hodnotu.

procedure seznam_int.vypiš_prvek(x:pointer)
begin
     writeln(ukinteger(x)^);
end
function porovnej(x,y:pointer):integer
porovná hodnoty dvou parametrů a vrací -1/0/1 je-li první větší/roven/menší než druhý

Tato metoda je použita v metodě vlož, pro správné zatřídění nového prvku

Obě metody jsou definovány jako virtuální. V odvozených třídách (seznam_string) předefinovánáme pouze tyto metody. Vše ostatní je zajištěno dědičností a polymorfismem OOP.
type seznam_string = object(seznam_int)
        procedure vypiš_prvek(x:pointer); virtual;
        function porovnej(x,y:pointer):integer; virutal;
     end;

Varianta II.

Máme pouze jednu třídu seznam a hierarchii tříd prvků, které do seznamu vkládáme. Typ_hodnoty bude ukprvek, což je ukazatel na abstraktní třídu prvek, od které jsou odvozeny všechny další třídy.

Třída prvek obsahuje pouze dvě metody:

procedure vypiš
vypíše danou instanci na standardní výstup; nemá žádný parametr -- hodnota se bere z vlastní instance
function porovnej(x:ukprvek):integer
porovná danou instanci s hodnotou parametru a vrací -1/0/1 stejně jako metoda porovnej v I. variantě.
Protože se jedná o abstarktní třídu, jsou obě metody virtuální a každý potomek by měl obě metody předefinovat. V našem případě tedy vytvoříme dvě třídy prvek_int a prvek_string, obě odvozené od třídy prvek. Každá třída si definuje nový datový prvek, který nese vlastní hodnotu. Dále definuje konstruktor, který instanci iniciailzuje podle zadaného parametru.
type prvek_string = object(prvek)
        hods: string;
	constructor init(s:string);
        procedure vypiš; virutal;
	function porovnej(x:ukprvek):integer; virutal;
     end;

constructor prvek_string.init(s:string);
begin
    hods := s;
end;

procedure prvek_string.vypiš;
begin
    writeln(hods);
end;

V metodě porovnej se nevyhneme přetypování, takže bude obsahovat kód ve tvaru:
     if (hods < ukprvek_string(x)^.hod) ....

Varianta III.

Máme hierarchii tříd prvků stejně jako v II. variantě a navíc máme hierarchii tříd seznamů.

Základní třída seznam definuje metodu vlož tak, že prvek vkládá na začátek seznamu a tedy vůbec nepoužívá metodu porovnej instancí jednotlivých prvků. To nám umožňuje vkládat do seznamu prvky různých typů (jak instance prvek_int, tak prvek_strign). Vypsání seznamu se provede správně -- pro každý prvek se volá jemu odpovídající metoda vypiš.

Od třídy seznam odvodíme třídu seznam_usp, která pouze předefinuje metodu vlož tak, aby v seznamu byly prvky pouze jednoho typu. Tj. před vlastním vložením porovná typ nového prvku s nějakým prvkem seznamu a pokud jsou různého typu, vložení neprovede.

procedure seznam_usp.vlož(x:ukprvek)
begin
     if (typeof(x^) <> typeof(zac^.hod^)) 
         {chyba} ...
     else
         {vložení}
         ...
end