Ať je vám to k užitku.
Přesně tak.> PRIVATE x PUBLIC tady jsem narazila na par nesrovnalosti, kdyz jsem
> porovnavala informace z ruznych zdroju a nevim jestli jsme to
> pochopila spravne. cilem ojektu by melo bbyt uchranit si sve datove
> polozky pred zasahy z venci, proto vetsina jazyku ma datove polozky
> nastaveny jako privatni.
Přesněji řečeno, implicitně jsou položky v TP veřejné. Tuto implicitní> vyjimku tvori TP, ktery je ma verejne a
> utajit se nam je podari jen s pouzitim klicoveho slova PRIVATE.
ochranu lze změnit použitím slova "private". Pokud private neuvedeme,
třída se bude chovat, jako bychom u položky uvedli "public".
Ano.takze zalezi v jakem jazyce programuji???
Public znamená, že položka je přístupná zvenčí (pokud nenapíšeme nic,> asi kdyz ted pouzivam TP tak bych
> mela pouzivat PRIVATE.... taky jsem objevila, ze existuje taky
> neco jako PUBLIC, ale uz nebylo popsano kde a jak se to pouziva....
pak to má tentýž efekt, jako kdybychom napsali "public", tedy aspoň v
Pascalu).
Klíčové slovo "public" se hodí, pokud chceme v definici třídy uvést
nejprve soukromé a až za nimi privátní položky. Pak můžeme psát:
Kód: Vybrat vše
type zvire = object
private
vek: integer;
hmot: integer;
bydl: kontinent;
public
constructor vyrob;
procedure mluv;
end; {of object zvire}
Datové položky by veřejné neměly být nikdy. Veřejné musí být všechny> co
> by teda melo byt verejne a co soukrome???
metody, u kterých chceš, aby je mohl volat uživatel. Naopak například
pomocné metody by měly být privátní.
V příloze posílám "praktickou" ukázku použití.> ja jsem to pochopila tak, ze
> uzivatel by se mel dostat jen k hlavicce metody, ale jak to funguje a
> jak se inicializuji, meni datove polozky by melo byt soukrome a jen v
> reziji programatora. jak se to ovsem ralizuje v praxi???
Vedle jak ta jedle. Abstraktní metoda je metoda, která nemá tělo. Jenom> ABSTRAKTNI x VIRUALNI metody abstraktni metody ma kryl uvedeny v
> pozadavcich, ale ja jsem na ne nikde nenarazila. tudiz se domnivam, ze
> by to mohly byt ty virtualni.
hlavičku. To znamená, že ji nelze volat (pochopitelně, co by se
provedlo, když nemá tělo...). Její tělo se definuje až v podtřídě (=
potomkovi, třídě, která z ní vznikne děděním). Abstraktní metoda má
smysl, pokud se nachází ve třídě, ze které neplyne, co přesně by metoda
měla dělat.
Tak například: Pokud máme třídu Okno a v ní metodu vykresliSe, je jasné,
že tato metoda smysl má, neboť každé okno se musí umět vykreslit. Není
však jasné, jak přesně by se okno mělo vykreslit. Jinak se totiž bude
vykreslovat okno pod Windows, jinak třeba okno v dosovském okně (takové
ty modré hnusy například v Turbo Pascalu). Proto třídě Okno vytvoříme
dva potomky: WindowsovskeOkno a DosovskeOkno. Obě tyto třídy budou dědit
od třídy Okno. Zatímco Okno neimplementovalo metodu vykresliSe, třídy
WindowsovskeOkno a DosovskeOkno už ano, protože víme, o jaký druh okna
se jedná a jak jej tedy vykreslit.
Poznámka: Pascal bohužel dovoluje vytvářet i objekty abstraktních tříd a abstraktní metody v Pascalu tělo mají - jeho úkolem je však vrátit chybu:
Kód: Vybrat vše
procedure mojeAbstraktniMetoda;
begin
runerror(211);
end;
Není pravda, že se musí inicializovat před každým použitím virtuální> tady me zaujala VMT, to ze se musi pred
> kazdym pouzitim virtualni metody inicializovat pomoci CONSTRUCTORU
> beru jako fakt, ale zajimalo by me, v cem ta inicializace spociva.
metody, stačí jen jednou, dříve, než se použije jakákoliv virtuální metoda.
VMT neexistuje pro každý objekt, ale pro každou třídu. Každý objekt ale> kazdy objekt ma jen jednu VMT pro vsechny svoje virtualni metody?
obsahuje odkaz do tabulky virtuálních metod. A tento odkaz vyplní konstruktor.
Zkusím to popsat na příkladě. Mějme třídy:> jak
> je velka, co kdyz budu mit spoustu vitualnich metod? (ciste
> hypoteticka otazka, protoze nepredpokladam, ze bych k tomu v praxi kdy
> dospela, ale vsude se pise, jak je VMT dulezita, al evic informaci o
> ni neni, tak by me to jen trochu zajimalo:)
Kód: Vybrat vše
Ctverec = object
procedure vykresliSe; virtual;
procedure nastavRozmery(rozmery: Dimension); virtual;
end;
ZaoblenyCtverec = object (Ctverec)
procedure vykresliSe; virtual;
nastavMiruZaobleni(zaobleni: Integer); virtual;
end;
VyplnenyCtverec = object (Ctverec)
procedure vykresliSe; virtual;
nastavBarvuVyplne(barva: Color); virtual;
end;
procedure Ctverec.vykresliSe;
begin
for i := 1 to 4 do nakresliCaru;
end;
procedure Ctverec.nastavRozmery(rozmery: Dimension);
begin
r := rozmery;
end;
procedure ZaoblenyCtverec.vykresliSe;
begin
for i := 1 to 4 do nakresliCaru;
zaobliRohy(z);
end;
procedure ZaoblenyCtverec.nastavZaobleni(zaobleni: Integer);
begin
z := zaobleni;
end;
procedure vyplnenyCtverec.vykresliSe;
begin
for i := 1 to 4 do nakresliCaru;
vyplnVnitrek(b);
end;
procedure vyplnenyCtverec.nastavBarvuVyplne(barva: Color);
begin
b := barva;
end;
Kód: Vybrat vše
VMT_Ctverec:
(vykresliSe) --------------------> {for i := 1 to 4 do nakresliCaru;}
(nastavRozmery) -----------------> {r := rozmery}
Kód: Vybrat vše
VMT_ZaoblenyCtverec:
(vyresliSe) ---------------------> {for i := 1 to 4 do nakresliCaru; zaobliRohy(z);}
(nastavZaobleni) ----------------> {z := zaobleni;}
(nastavRozmery) -----------------> {r := rozmery}
Kód: Vybrat vše
VMT_VyplnenyCtverec:
(vyresliSe) ---------------------> {for i := 1 to 4 do nakresliCaru; vyplnVnitrek(b);}
(nastavBarvuVyplne) -------------> {b := barva;}
(nastavRozmery) -----------------> {r := rozmery}
odkaz na implementaci této metody, která se má pro danou třídu volat.
Protože metoda vykresliSe je třídami ZaoblenyCtverec a VyplnenyCtverec
předefinovaná, míří v každé VMT odkaz pro vykresliSe jinam. Na druhou
stranu, metoda nastavRozmery předefinovaná není, takže v každé VMT míří
odkaz pro nastavRozmery na stejné místo.
A teď k úloze konstruktoru. Nechť objekt "a" vytvoříme takto:
1)
Kód: Vybrat vše
var a: Ctverec;
new(a, init);
2)
Kód: Vybrat vše
var b: ZaoblenyCtverec;
new(b, init);
Totéž pro vyplněný čtverec.
A pozor, to není vše! Pokud bychom napsali:
Kód: Vybrat vše
procedure maluj(var c: Ctverec);
begin
c.vykresliSe;
end;
maluj(b); {<<< TOTO JE PODSTATNÉ !!!}
je typu Ctverec, nikoliv ZaoblenyCtverec. To proto, že "c" je sice typu
Ctverec, ale byl vytvořen konstruktorem pro ZaoblenyCtverec. Proto má v
sobě ukazatel na tabulku VMT_ZaoblenyCtverec.
Destruktor slouží ke zrušení všeho, co objekt během svého života> taky jse m narazila na DESTRUKTOR, ktery by se mel rusit virtualni
> metody. to ze je taky virtualni, je mi uplne jasne a doufam ze jsem
> vstrebala i rozdil mezi dispose a destruktorem. pokud mam dynamicky
> alokovanou promennou objektoveho typu a uz ji nepotrebuji, tak nejdrive
> pouziji destruktor a zrusim virualni metody a pak zavolam dipose, ktery
> smaze obsah promenne a uvolni pamet. jak si jeste matne vzpominam, tak
> kryl na prednasce uvadel, ze destruktor se nemusi pouzivat, ale asi k
> necemu slouzit bude, kdyz uz ho vytvorili, ne?
napáchal. Tak například, dejme tomu, že implementuješ spojový seznam
objektově. Vytvoříš si objekt s názvem "seznam" a voláš na něm metody:
Kód: Vybrat vše
seznam.pridejNaZacatek(50);
seznam.pridejNaZacatek(5);
seznam.pridejNaZacatek(10);
seznam.pridejNaZacatek(4);
tato paměť se někdy musí opět uvolnit. A to je právě práce pro
destruktor. Pozor, dispose zavolané na objektu "seznam" samo o sobě
nepomůže, to zruší objekt "seznam" jako takový. Nezruší však to, co
objekt "seznam" naalokoval během svého života.
Nebo další příklad. Vytvoříme objekt typu "spojeni", který bude
reprezentovat síťové spojení. Zase, je slušností někdy spojení uzavřít
(analogie položení sluchátka) a to je právě práce pro destruktor!
Ne spíše abstraktní třída? Abstraktní třída je třída, která má aspoň> ABSTRAKTNI OBJEKT
> tak tady v tom plavu , ba se dokonce topim. nikde jsem na to nenarazila a moje poznamky z prednasky nestoji za nic.
> mohl bys mi to prosim objesnit?
jednu abstraktní metodu. Ve výše uvedeném příkladu by například třída
Okno byla abstraktní, zatímco třídy WindowsovskeOkno a DosovskeOkno už
nikoliv. Abstraktní objekt... Pokud to opravdu existuje, pak se
domnívám, že je to objekt abstraktní třídy. To je taková úchylárna
Pascalu. Pascal umožňuje instanciovat i abstraktní třídy. Slušné
programovací jazyky toto nedovolí.
Platí toto: vždy lze přiřadit potomka do předka, nikoliv naopak. Takže:> DEDICNOST a PRIRAZOVANI
> tady mi neni uplne jasne jestli muzu promennou typu "potomek" priradit promenne typu "PREDEK" nebo naopak.
> napr. typ auto=object......
> typ osobni=object (auto)
> var felicie:osobni;
> male:auto;
>
> osobni je potomek auta a ma dalsi specificke metody. no a v prubehu programu budu treba potrebovat priradit do male:=auto....
> cimz ztratim specificke vlastnosti auta(metody co ma navic)....nebo to je nekorektni a funguje auto:=male???
> z toho jsem celkem zmatena
Kód: Vybrat vše
zvire := kocka;
auto := dodavka;
Důvod: Takzvaný IS-A princip (van IS A car, cat IS A beast,...). Tedy,
protože kočka je zvíře, lze do proměnné typu zvíře přiřadit kočku. A
protože dodávka je auto, lze do proměnné typu auto přiřadit dodávku.
Naopak to nejde. Představ si toto:
Kód: Vybrat vše
zvire := pes;
kocka := zvire; {...kdyby to šlo}
tohoto důvodu je přiřazení typu kocka := zvire zakázané.
Je sice pravda, že přiřazením zvire := kocka se ztratí specifické
vlastnosti kočky, určitě pak nebude možné volat třeba metodu
zvire.mnoukej. To ale nevadí. Pokud programátor přižazuje do nadtřídy
(= předka), ví, co dělá, tedy je si vědom, že specifické vlastnosti
přiřazovaného objektu nebude potřebovat. Navíc, specifické vlastnosti
se neztratí úplně. Podívej se výš na příklad se čtverci. Konkrétně na
metodu "maluj". Tato metoda bere parametr typu Ctverec a přesto je
schopná kreslit i vyplněné či zaoblené čtverce. Proč? Volá totiž
virtuální metodu vykresliSe. A právě díky virtualitě to funguje.
Tak jeden příklad na self. Dejme tomu, že máš metodu nastavZaobleni> hrebicek do rakvicky mi jeste pridali SELF a INHERITED.....
deklarovanou takto:
Kód: Vybrat vše
procedure nastavZaobleni(z: Zaobleni);
než budeš pokračovat dál!
V čem se liší? V nejedoznačnosti "z" (když se v těle zapíše "z", neví
se, jestli se tím rozumí členská proměnná "z" nebo parametr "z"). Tento konflikt se vyřeší napsáním:
Kód: Vybrat vše
procedure nastavZaobleni(z: Zaobleni);
begin
self.z := z; {doufam, uz ten Pascal moc neumim...}
end;
1) V předkovi máš metodu A a v potomkovi jsi ji předefinovala. Ale z
potomkovy metody dejme tomu B chceš volat metodu A, ale ne tu
předefinovanou, nýbrž tu původní, co byla v předkovi, pak ji musíš
kvalifikovat napsáním inherited.
2) V potomkovi předefinuješ metodu A a z této předefinované metody
chceš zavolat metodu A předka (třeba k metodě A chceš v potomkovi
přidat nějakou funkcionalitu, takže nejprve zavolaš původní předkovskou
metodu a pak provedeš další příkazy, které tam tu funkcionalitu
přidají). Nemůžeš předkovskou metodu ale volat pouhým napsáním A. To
bys (rekurzivně!) zavolala metodu A potomka. Proto musíš volání metody
A kvalifokovat připsáním inherited.
> SELF je odkaz, ze pouzivam metodu vlastni danemu objektu a INHERITED, ze pouzivam metodu meho predka...kdy se to vlastne pouziva???
>
> doufam, ze jsem ted nezavarila na gulas ja tobe:(
>
> taky se uz ucim dalsi teorii a mela bych jeste dotazek mimo objekty
Pomalejší je předávání hodnotou, a to proto, že hodnota se musí> HODNOTA a REFERENCE:)
> jake jsou rozdilzy mezi predavani parametru hodnotou a refernci jsem pochopila, ale nejsem si uplne jista co je rychlejsi. me se jevi jako rychlejsi a pametove mene narocnejsi predavani hodnotou. protoze u predavani odkazem, se nejprve preda odkaz a pak se jeste musi najit adresu a pak pouzit informace. z cehoz usuzuji, ze jednoduch predani hodnoty, prirazeni informace do formalniho paramentru, je o dost jednodussi.
> co se nesmi predavat hodnotou a co se nesmi predavat odkazem???
kopírovat. Což o to, když je parametr typu Integer, tak to nevadí. A co
když je parametr typu "record" a ten obsahuje třeba dvacet položek? Pak
to kopírování opravdu zpomaluje.
Odkazem se předávat doporučuje:
Cokoliv, co je velké (record, objekt), tudíž kopírování hodnoty by zdržovalo.
Odkazem se předávat musí:
Proměnná, jejíž hodnotu chceme zevnitř volané funkce/procedury měnit.
Hodnotou se předávat doporučuje:
Cokoliv, co je malé (Integer) a hodnotu čehož nechceme z vnitřku funkce měnit.
Hodnotou se předávat musí:
Literály (tj. konstanty).
Toto by nefungovalo: procedure mojeProcedura(var cislo);
mojeProcedura(6378);
Důvod: při předávání odkazem se předává ODKAZ NA PROMĚNNOU. A 6378 není proměnná.
Například inicializované pole:> INICIALIZOVANE promene (strukturovane konstanty)
> vim, ze jsem v cervnu na to nekde narazila, ale ted uz nejsem schopna to dohledat, mohl bys mi objasnit jeste tohle?
Kód: Vybrat vše
const d: array[1..n, a..n] of Integer = ((-1, 2), (1, 2), (2, 1), (2, -1), ... a tak dále ...);
Zásadní otázka, dobře, že ses zeptala. Třída je třeba Kocka, Pes, Okno.mohl bys mi vysvetlit rozdil mezi tridou a
> objektem? jako tridu si predtavim zvirata a podtrida kockopes:P ale to
> jsou prece objekty, ne? nejak v tom nemam jasno, hotovy zverinec:)
Objekt je pak instance třídy, tedy pokud napíšeš:
Kód: Vybrat vše
var micka, cert, mourek, mikes: Kocka;
bara, lumpik, kendy: Pes;
chybovaHlaska, prihlasovaciDialog: Okno;
prihlasovaciDialog jsou všechno objekty.
příloha
Kód: Vybrat vše
type kontinent = (AFRIKA, EVROPA, ANTARKTIDA);
type zvire = object
private
vek: integer;
hmot: integer;
bydl: kontinent;
public
constructor vyrob;
procedure mluv;
end; {of object zvire}
type pes = object (zvire)
private
zuby: integer;
public
constructor vyrob;
procedure mluv;
end; {of object pes}
constructor zvire.vyrob;
begin
vek := 10;
hmot := 5;
bydl := EVROPA;
end;
procedure zvire.mluv;
begin
writeln ('Mluvim.', vek: 10, hmot: 10);
end;
constructor pes.vyrob;
begin
zvire.vyrob;
zuby := 22;
end;
procedure pes.mluv;
begin
writeln ('Haf!', zuby:10);
end;
type pZvire = ^zvire;
type pPes = ^pes;
var mojeZvire: pZvire;
var mujPes: pPes;
begin
new (mujPes);
mujPes^.vyrob;
mujPes^.mluv;
writeln;
mojeZvire := mujPes;
mojeZvire^.mluv;
end.