Autor Téma: Přístup k vlastnostem objektu vytvořeného z třídy která je potomkem  (Přečteno 213 krát)

Offline Stanislav B

  • Nováček
  • *
  • Příspěvků: 4
  • Karma: 0
    • Verze Delphi: 7, RAD Studio 2010
Zdravím. Sháním někoho, kdo by mi v klidu vysvětlil jednu vlastnost v oblasti dědičnosti, kterou jsem na internetu nenašel a ani tady na formu (je možné, že se špatně ptám). Moc nevím, jak to nazvat, tak problém popíši na ukázce. V oblasti Delphi jsem spíše samouk, co si píše mini programy jako nástroje pro ulehčení své práce. 
Problém:
   Mějme třídu „PT“, která je potomkem třídy „T“. Ve svém kódu vytvořím objekt „O“, který vychází z třídy „PT“. „O“ má v tuto chvíli díky dědičnosti dostupné vlastnosti třídy „T“ (přes tečku). Nyní chci přidat vlastní procedury/funkce do „PT“, které mi práci s objektem „O“ rozšíří. Teď je ta otázka. Jak mohu v proceduře, která se nachází v třídě PT vzít nějakou vlastnost objektu „O“ a tam s ním pracovat?
Příklad: Mám třídu, TExtendStringList, která dědí z TStringList. Vytvořím objekt Log, který vychází z třídy TExtendStringList. Do Log načtu nějaký text, ať už přiřazením, nebo načtením ze souboru. V třídě TExtendStringList pak chci napsat proceduru DeleteA, která (teď střílím) odstraní z textu všechny ‘a’ .
Otázka: Jak se v proceduře DeleteA která je umístěna v třídě TExtendStringList odkázat na objekt Log, se kterým chci pracovat? Nemám na mysli že bych ho předával jako parametr. Chtěl bych to čisté, obdobě jako když StringList, kde je přes tečku dostupné například „Add, Exchange, Find“ též v parametru nepředávají objekt TStringList, nad kterým se má pracovat, a k tomu parametry dané funkce.  Děkuji

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 1185
  • Karma: 51
    • Verze Delphi: 10.3
Ahoj, snad jsem pochopil, co potřebuješ :)

Kód: Delphi [Vybrat]
  1. type T = class(tObject)
  2.       public
  3.        Text: string;
  4.      end;
  5.  
  6.      PT = class(T)
  7.       public
  8.        procedure DeleteA;
  9.      end;
  10.  
  11. var O: PT;
  12.  
  13. procedure PT.DeleteA;
  14.  begin
  15.  Text:=StringReplace(Text, 'a', '', [rfReplaceAll]);
  16. end;
  17.  
  18. ...
  19. O.DeleteA;



Offline Jan Fiala

  • Plnoletý
  • ***
  • Příspěvků: 179
  • Karma: 2
    • Verze Delphi: 10.4.1
    • PSPad editor
Pokud zdědíš objekt, pak public a protected vlastnosti jako Items, Strings, Objects i public a protected metody apod. jsou v potomkovi dostupné.
U Delphi je to trošku matoucí v tom, že pokud to je v rámci jedné unity, dostaneš se i na private vlastnosti, mimo unitu už ne.
to se autori snazili opravit a zavedli sekce jako strict private.

Některé věci můžeš ve svém potomkovi přepsat - třeba pokud bys chtěl metodu Delete, která by dělala něco navíc. Pak bys ji deklaroval v potomkovi a přidal bys "override" (přepsaná),
Kód: Delphi [Vybrat]
  1. procedure Delete(...); override;
mohl bys ji uvnitř celou přepsat a udělat si to po svém nebo jen udělat, co potřebuješ navíc a zavolat "inherited", čímž by se provedla standardní funkčnost Delete z předka.
Nemusíš vytvářet novou DeleteA. To by pak vedlo k tomu, že bys v potomkovi viděl jak Delete, tak i DeleteA. Nechtěně pak zavoláš Delete a budeš hledat, kde je problém. Sice by se to dalo v potomkovi vyřešit "skrytím" Delete z předka, ale je to kód na víc, který by nepřispíval čitelnosti.

Offline Stanislav B

  • Nováček
  • *
  • Příspěvků: 4
  • Karma: 0
    • Verze Delphi: 7, RAD Studio 2010
Pánové, děkuji Vám za rychlé reakce. Obě věci mi dávají smysl. Vandrovník ukazuje příklad, kdy vím, že předek má v public sekci proměnou, ke které mohu přistupovat a se kterou lze dále pracovat.
Jan Fiala v prvním odstavci de facto textově popal, to, co vandrovník napsal ukázkou (přístup k proměnné předka), v druhém mi dobře přiblížil využití „inherited“. Děkuji.
Suma sumárum je takové, že když chci přistupovat k obsahu nějakého objektu, který je vytvořen z nějaké třídy, byť už předprogramované vývojáři, musím si v unitech, nebo pod „tečkami“ najít, to co mi veřejně nabízí. Když tam nějaký zamyšlený obsah nebude, mám smůlu. Přeneseno na zmíněný TStringList pokud z něj budu dědit do TExtendStringList a v TExtendStringList budu chtít psát nějakou proceduru, co pracuje s textem (jedno jakou, ať se nedržíme toho delete ), tak se k tomuto textu v objektu nedostanu, neboť TStringList nemá ve veřejném rozhraní možnost k němu přistupovat a tak se nemám procedurou xy v TExtendStringList k textu možnost dostat. Je tak?

Unit1
Kód: Delphi [Vybrat]
  1. uses SysUtils, ...., Unit2;
  2. type
  3. THlavniTrida = class (TObject)
  4. public
  5. procedure zpracujText();
  6. end;
  7.  
  8. var Log : TExtendStringList;
  9.  
  10. implementation
  11.  
  12. // procedury create a naplnění proměnné Log textem
  13.  
  14. procedure THlavniTrida.zpracujText(); // procedura co něco dělá s textem, třeba parser
  15. begin
  16. Log.parser();
  17. end;
  18. end.
  19.  

Unit2
Kód: Delphi [Vybrat]
  1. uses SysUtils, ....;
  2. type
  3. TExtendStringList = class (TStringList)
  4. public
  5. procedure parser();
  6. end;
  7.  
  8. implementation
  9.  
  10. procedure TExtendStringList.parser();
  11. begin
  12. //v této proceduře se chci dostat na text, který je obsahem Log, ať ho můžu zpracovat
  13. end;
  14. end.
  15.  


Snad táto ukázka bude více srozumitelná.

Offline starous

  • Mladík
  • **
  • Příspěvků: 95
  • Karma: 3
    • Verze Delphi: Delphi 7, Delphi 10.4
Přeneseno na zmíněný TStringList pokud z něj budu dědit do TExtendStringList a v TExtendStringList budu chtít psát nějakou proceduru, co pracuje s textem (jedno jakou, ať se nedržíme toho delete ), tak se k tomuto textu v objektu nedostanu, neboť TStringList nemá ve veřejném rozhraní možnost k němu přistupovat a tak se nemám procedurou xy v TExtendStringList k textu možnost dostat. Je tak?

To ses tedy podíval špatně. Property Text je u TStringList veřejná, takže bude veřejná i ve zděděné třídě. Prostě normálně v té metodě Parser pracuj s proměnnou Text.

Kód: Delphi [Vybrat]
  1. procedure TExtendStringList.parser();
  2. var
  3.   CastTextu : string;
  4. begin
  5.    CastTextu := copy(Text, 1, 10);  // treba me zajima jen prvnich 10 znaku
  6.    ...
  7. end;
  8.  
« Poslední změna: 10-03-2021, 00:05:59 od starous »

Offline Stanislav B

  • Nováček
  • *
  • Příspěvků: 4
  • Karma: 0
    • Verze Delphi: 7, RAD Studio 2010
Výborně, ve spojení všech tří odpovědí jsem to dal dohromady. Ano, je to tedy tak, že se musí dohledat proměné dané třídy, jejichž obsah chci ve zděděné třídě použít. Ano v TStringList taková je, avšak ne přímo ve TStringList ale předkovi TStringList, tj. TString. Je tam proměnná text, poté, co jsem se na základně příspěvku Starouše na to zaměřil jsem ji našel, avšak to není tá co je pro práci s StringListem za potřebí. Je to lineární proměnná, respektive text s jedním řádkem. To, co jsem hledat pro případ StringList je proměnná Strings v TString. Tu reprezentuje pole a je možné pracovat se znaky na základě řádku a sloupce Strings[řádek][sloupec]. Takže ještě jednou děkuji. Situace vyřešena.

Offline Jan Fiala

  • Plnoletý
  • ***
  • Příspěvků: 179
  • Karma: 2
    • Verze Delphi: 10.4.1
    • PSPad editor
Ono to funguje tak, že pokud je nejaká property zveřejněna (public) v předkovi nahoře a dál se práce s ní nemění (klidně několik generací potomků), pak je při dědění k dispozici.

To se třeba týká i základních věcí jako Name, Tag, Class apod. Ty pochází z nějakého základního předka a dál je pak už neuvádíš.