PL/SQL v příkladech / Dědičnost a polymorfismus
Klíčovým konceptem objektově orientovaného programování (OOP) je dědičnost, která umožňuje seskupovat vlastnosti a chování do hierarchie. Tímto způsobem mohou nové objekty automaticky získat funkcionalitu (metody, proměnné, konstanty atp.) ze svého předka.
Ve výchozím stavu objekt dědičnost zakazuje, proto je nutná úprava modifikátorem NOT FINAL
.
CREATE OR REPLACE TYPE Zamestnanec_T AS OBJECT( CeleJmeno VARCHAR2(100) , MEMBER FUNCTION mf_Vypis RETURN VARCHAR2 ) NOT FINAL; /
CREATE OR REPLACE TYPE BODY Zamestnanec_T AS MEMBER FUNCTION mf_Vypis RETURN VARCHAR2 IS BEGIN RETURN CeleJmeno; END; END; /
Překrývání
Dalším velmi rozšířeným konceptem OOP je překrývání metod. To umožňuje podtypům měnit chování zděděných procedur a funkcí a přizpůsobit je konkrétním požadavkům.
Definice metody zůstává stejná jako v předkovi, jen je uvozena klíčovým slovem OVERRIDING
.
CREATE OR REPLACE TYPE Programator_T UNDER Zamestnanec_T( Plat NUMBER , OVERRIDING MEMBER FUNCTION mf_Vypis RETURN VARCHAR2 ); /
CREATE OR REPLACE TYPE BODY Programator_T AS OVERRIDING MEMBER FUNCTION mf_Vypis RETURN VARCHAR2 IS BEGIN RETURN CeleJmeno||', '||Plat; END; END; /
Použití překryté funkce mf_Vypis
je přímočaré, v prvním případě se vypíše pouze celé jméno, v druhém jméno i plat.
DECLARE l_Zamestnanec Zamestnanec_T; l_Programator Programator_T; BEGIN l_Zamestnanec:=Zamestnanec_T('Franta Vomacka'); dbms_output.put_line(l_Zamestnanec.mf_Vypis); -- Franta Vomacka l_Programator:=Programator_T('Petr Novak', 20000); dbms_output.put_line(l_Programator.mf_Vypis); -- Petr Novak, 20000 END;
Polymorfismus
Zajímavá situace nastává, když je potomek přiřazen do proměnné předka, tedy do Zamestnanec_T
. V tomto případě se vypíše jméno společně s platem. Je to proto, že objekt je ve skutečnosti instancí typu Programator_T
. Technika, kdy objekty s různými typy reagují na volání specifickým způsobem, se nazývá polymorfismus.
DECLARE l_Zamestnanec Zamestnanec_T; BEGIN l_Zamestnanec:=Programator_T('Petr Novak', 20000); dbms_output.put_line(l_Zamestnanec.mf_Vypis); -- Petr Novak, 20000 END;
Pokud je potřeba z nějakého důvodu vynutit implementaci definovanou v předkovi na potomkovi, který ji překrývá, je nutná explicitní konverze.
DECLARE l_Programator Programator_T; BEGIN l_Programator:=Programator_T('Petr Novak', 20000); dbms_output.put_line((l_Programator AS Zamestnanec_T).mf_Vypis); -- Petr Novak END;