Autor Téma: TfrmFormMain = class(TBasalForm) -> nezbehnú udalosti v TBasalForm  (Přečteno 905 krát)

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 3833
  • Karma: 35
    • Verze Delphi: XE7 professional

Kód: Delphi [Vybrat]
  1. unit BasalForm;
  2. interface
  3. type
  4.   TBasalForm = class(TForm)
  5.   strict protected
  6.     procedure CreateObjects; virtual;
  7.     procedure CreateSQL; virtual;
  8.     procedure SetForm; virtual;
  9.   public
  10.     constructor CreateForm;
  11.     destructor Destroy; override;
  12.     property pRecord: TList<Pointer> read FpRecord;
  13.   end;
  14. implementation
  15. constructor TBasalForm.CreateForm;
  16. begin
  17.   inherited Create(nil);
  18.   SetForm;
  19. end;
  20.  
  21.  
  22. destructor TBasalForm.Destroy;
  23. begin
  24.   if Assigned(oGlobalVar) and (oGlobalVar.ListOfObjects.Count > 0) then
  25.     oGlobalVar.DestroyObjects;
  26.   inherited;
  27. end;
  28.  
  29.  
  30. procedure TBasalForm.CreateObjects;
  31. begin
  32. end;
  33.  
  34.  
  35. procedure TBasalForm.CreateSQL;
  36. begin
  37. end;
  38.  
  39.  
  40. procedure TBasalForm.SetForm;
  41. begin
  42.   CreateSQL;
  43.   CreateObjects;
  44. end;
Všade to funguje (CreateForm, Destroy), len pre hlavný formulár aplikácie nie. Ten vytváram až po spustení aplikácie dynamicky. Netuším prečo a tak to neviem spojazdniť.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Delfin

  • Padawan
  • ******
  • Příspěvků: 1527
  • Karma: 61
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Jakym zpusobem vytvaris ten hlavni form? Tvoris jej pomoci TApplication.CreateForm? Pokud ano, pak vez, ze ta zminovana metoda vola konstruktor Create.
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 3833
  • Karma: 35
    • Verze Delphi: XE7 professional
Áno, tvorím ho tak. Takže jedna vec je jasná. Ako dosiahnem, aby sa mi zavolal BasalForm.Create?
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Delfin

  • Padawan
  • ******
  • Příspěvků: 1527
  • Karma: 61
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Kód: Delphi [Vybrat]
  1. type
  2.   TBasalForm = class(TForm)
  3.   public
  4.     constructor Create(AOwner: TComponent = nil); reintroduce; override; // nepovinny parametr
  5.   end;
  6.  
  7. implementation
  8.  
  9. constructor TBasalForm.Create(AOwner: TComponent = nil); // nepovinny parametr
  10. begin
  11.   inherited Create(AOwner);
  12.   ...
  13. end;
« Poslední změna: 25-01-2019, 13:12:27 od Delfin »
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 3833
  • Karma: 35
    • Verze Delphi: XE7 professional
Ďakujem, už to ide. A ja si pozriem prečo.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Delfin

  • Padawan
  • ******
  • Příspěvků: 1527
  • Karma: 61
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Ja jen prekryl a schoval puvodni konstruktor Create formulare (jenz se vola uvnitr metody TApplication.CreateForm) konstruktorem s nepovinnym parametrem takze je mozne jej volat i bez parametru (cimz se do vlastnika formulare dosadi nil).

P.S. k vytvoreni metod bez implementace je vhodnejsi pouzit direktivy virtual; abstract; nez jen virtual s prazdnou implementaci. Metody by vzdy nejakou implementaci mit mely; pokud realnou implementaci neobsahuji, mely by alespon vyvolat vyjimku ENotImplemented, pripadne ENotSupportedException.
« Poslední změna: 25-01-2019, 13:50:21 od Delfin »
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2398
  • Karma: 129
    • Verze Delphi: D2007, XE3, DX10
P.S. k vytvoreni metod bez implementace je vhodnejsi pouzit direktivy virtual; abstract; nez jen virtual s prazdnou implementaci. Metody by vzdy nejakou implementaci mit mely; pokud realnou implementaci neobsahuji, mely by alespon vyvolat vyjimku ENotImplemented, pripadne ENotSupportedException.
To je hloupost: pokud pouzivam polymorfismus, tak existuji dva zakladni pripady:
- chci prinutit kazdeho potomka, ze neco musi implementovat, tak pouziju abstract
- chci dat kazdemu potomkovi moznost prekryt implicitni chovani a pak pouziju virtual a v bazalni tride udelam spolecnou implementaci, treba prazdnou by default.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 3833
  • Karma: 35
    • Verze Delphi: XE7 professional
Práve som napísal odpoveď, ale toto je podstatne lepšie a výstižnejšie.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Delfin

  • Padawan
  • ******
  • Příspěvků: 1527
  • Karma: 61
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
To je hloupost: pokud pouzivam polymorfismus, tak existuji dva zakladni pripady:
- chci prinutit kazdeho potomka, ze neco musi implementovat, tak pouziju abstract
- chci dat kazdemu potomkovi moznost prekryt implicitni chovani a pak pouziju virtual a v bazalni tride udelam spolecnou implementaci, treba prazdnou by default.

S tou prazdnou metodou nesouhlasim. Pokud nema metoda implementaci, mela by byt abstraktni. Pokud i presto chces implementaci deklarovat, mel bys IMHO stejne jako v pripade volani neprekryte abstraktni metody vyvolat vyjimku.
« Poslední změna: 25-01-2019, 15:16:25 od Delfin »
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Offline pepak

  • Guru
  • *****
  • Příspěvků: 1389
  • Karma: 34
    • Pepak.net
Excellent
Rated 1 time
S tou prazdnou metodou nesouhlasim. Pokud nema metoda implementaci, mela by byt abstraktni. Pokud i presto chces implementaci deklarovat, mel bys IMHO stejne jako v pripade volani neprekryte abstraktni metody vyvolat vyjimku.
Ty necítíš rozdíl mezi metodou, která nemá implementaci, a metodou, která má implementaci, která nic nedělá? Nebo jsi zastáncem názoru, že metoda TObject.AfterConstruction měla být deklarována jako abstract, protože přece nemá implementaci a každý potomek TObject si ji může snadno naimplementovat podle svých představ?

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 3833
  • Karma: 35
    • Verze Delphi: XE7 professional
Citace
Pokud i presto chces implementaci deklarovat, mel bys IMHO stejne jako v pripade volani neprekryte abstraktni metody vyvolat vyjimku.
A toto je vec ktorej nerozumiem. Prečo mám obsluhovať nejakú výnimku, keď to nie je chyba, ale zámer (prázdna rutina)? Môžeš mi to vysvetliť? A ani si neviem predstaviť ako by taká obsluha výnimky mala vyzerať.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2398
  • Karma: 129
    • Verze Delphi: D2007, XE3, DX10
TObject.AfterConstruction měla být deklarována jako abstract, protože přece nemá implementaci a každý potomek TObject si ji může snadno naimplementovat podle svých představ?
Lepsi priklad pro Delphistu asi neexistuje.

Offline Delfin

  • Padawan
  • ******
  • Příspěvků: 1527
  • Karma: 61
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
S tou prazdnou metodou nesouhlasim. Pokud nema metoda implementaci, mela by byt abstraktni. Pokud i presto chces implementaci deklarovat, mel bys IMHO stejne jako v pripade volani neprekryte abstraktni metody vyvolat vyjimku.
Ty necítíš rozdíl mezi metodou, která nemá implementaci, a metodou, která má implementaci, která nic nedělá? Nebo jsi zastáncem názoru, že metoda TObject.AfterConstruction měla být deklarována jako abstract, protože přece nemá implementaci a každý potomek TObject si ji může snadno naimplementovat podle svých představ?

Jiste. Jen si stojim za tim, ze by takova metoda mela zajistit vyvolani udalosti nez nedelat vubec nic.

Citace
Pokud i presto chces implementaci deklarovat, mel bys IMHO stejne jako v pripade volani neprekryte abstraktni metody vyvolat vyjimku.
A toto je vec ktorej nerozumiem. Prečo mám obsluhovať nejakú výnimku, keď to nie je chyba, ale zámer (prázdna rutina)? Môžeš mi to vysvetliť? A ani si neviem predstaviť ako by taká obsluha výnimky mala vyzerať.

Pro me je prazdna metoda chybou implementace.
« Poslední změna: 25-01-2019, 21:07:28 od Delfin »
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Offline pepak

  • Guru
  • *****
  • Příspěvků: 1389
  • Karma: 34
    • Pepak.net
Jiste. Jen si stojim za tim, ze by takova metoda mela zajistit vyvolani udalosti nez nedelat vubec nic.
A řešit situaci, kdy stejnou "událost" bude chtít víc různých tříd v řetězci potomků, budeme jak? Seznamem zájemců o obsluhu události? Pořadí událostí bude určeno čím? Jak zařídím, aby potomek úplně nahradil událost z předka?

Jako pro mě za mě si tak programuj, ale můj názor je, že tvoje poněkud fundamentalistické lpění na událostech všude je pomalé, paměťově neefektivní, neohrabané a nedokáže řešit všechny situace, které mohou nastat. Neříkám, že nemáme nikdy používat události - někdy jsou užitečné, tak je použijme, ale podle mě je dobré mít na výběr. Tak, jak to je ve VCL - podle situace se rozhodnu, jestli chci dát událost do OnShow, nebo jestli overridnu DoShow.

Offline Delfin

  • Padawan
  • ******
  • Příspěvků: 1527
  • Karma: 61
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
A řešit situaci, kdy stejnou "událost" bude chtít víc různých tříd v řetězci potomků, budeme jak? Seznamem zájemců o obsluhu události? Pořadí událostí bude určeno čím?

Prekrytim a pridanim kodu implementace dane metody vyvolavajici udalost, jak jinak...

Jak zařídím, aby potomek úplně nahradil událost z předka?

Tim, ze nezavolas inherited, nebo snad nevis, co se ve Tvych tridach odehrava? Volat bezhlave inherited metody mi neprijde v poradku (opravdu je lepsi rict nejakym zpusobem, sorry, ja to, rekneme, "jeste" neimplementoval). Tedy, za me by mela pri volani takove metody alespon vypadnout chyba o chybejici implementaci nebo o volani abstraktni metody (coz se ostatne deje s direktivou abstract).

Jako pro mě za mě si tak programuj, ale můj názor je, že tvoje poněkud fundamentalistické lpění na událostech všude je pomalé, paměťově neefektivní, neohrabané a nedokáže řešit všechny situace, které mohou nastat.

Budu. A nejde o udalosti, jen o prazdne metody. Metoda podle me nema byt prazdna. Runtime chyba nebo minimalne varovani kompilatoru v pripade prazdne implementace metody je pro me minimem. Porad totiz nevidim argument, jenz by me presvedcil k tomu, abych nechal metodu prazdnou a z potomka volal inherited s tim, ze se nic nestane...

Jiste, spousta lidi si tu rekne, co zase ten delfin plodi za nesmysly, ale to jsem zazil. Lidi nebyli schopni ani vlozit do takove prazdne metody komentar, natoz napr. ToDo polozku...
« Poslední změna: 26-01-2019, 06:48:58 od Delfin »
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2398
  • Karma: 129
    • Verze Delphi: D2007, XE3, DX10
Jiste. Jen si stojim za tim, ze by takova metoda mela zajistit vyvolani udalosti nez nedelat vubec nic.
Mam dojem, ze sis zamenil doporuceni Composition over Inheritance za Composition instead of Inheritance...

Citace
abych nechal metodu prazdnou a z potomka volal inherited s tim, ze se nic nestane...
No to je to zakladni pomyleni dane tim absolutnim nahrazenim dedicnosti kompozici: tam skutecne kazdy musi implementovat metodu rozhrani... Ale pokud bazalni trida implementuje implicitni vlastnosti, tak vsechny odvozene tridy, pokud nepotrebuji menit implicitni vlastnosti, metodu vubec nekrekryvaji a tudiz ani nevolaji zadne inherited...

Jak kompozice, tak dedicnost maji svoje klady a zapory s tim, ze cim blize je vystavovane rozhrani blize aplikacni logice, tim mensi pocet metod zpravidla vystasvuje a tim vetsi vahu bude mit kompozice/delegovani pred dedicnosti. Ale pokud vlastnostni je hodne a odchylek od implicitniho chovani je malo, tak je nesmysl je delegovat, protoze to znamena obrovske mnozstvi zbytecne prace.

Vyborny priklad je to TObject.AfterContruction. Kdyby z toho udelali delegata, jaky overhead u kazde instance TObject by zbytecne zavedli ev. kdyby raisnuli exception (a tim vlastne simulovali to abstract), aby to nebylo prazdne, tak by to kazdy potomek TObject  musel prekryvat prazdnou metodou... To by byl blazinec k nepouziti.



Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2398
  • Karma: 129
    • Verze Delphi: D2007, XE3, DX10
Jiste, spousta lidi si tu rekne, co zase ten delfin plodi za nesmysly, ale to jsem zazil.
Tak ja popisu, co jsem zazil s tupe aplikovanou kompozici, kterou mel na svedomi taky mlady programator - mozna, ze takove ptakoviny skutecne nekde uci - budu se muset preptat  :)

- dostal na hrb soft pro pomerne slozite stroje, kde jeho customizaci resil interface
- na zacatku mel par zakazniku a par vlastnosti
- ale casem se mu pocet customizaci rozrostl na 100+ a pocet vlastnosti na rozhrani na stovky
- novou customizaci vytvarel Copy&Paste z nejake nejpodobnejsi
- novou vlastnost pridaval zpetne do 100+ implementaci intreface s tim, ze vsude byla 'prazdna' nebo implicitni
  krome toho jednoho prave pridaneho zakaznika...
- kdyz chtel nejakou vlastnost zmenit, musel prolezt 100+ interface...

Vyhodu to melo jedinou, ze kdyz nekde neco posr*l, tak to posr*l jen pro tu danou customaci, coz byla zrejme jeho primarni motivace k takovemu masochismu.

No a pak prisel pozadavek zmenit kompletne vsude ksicht podle navrhu graficky vcetne vzhledu gridu apod., coz mj. znamenalo rozsirit
pocet vlastnosti na rozhrani, protoze 2 zakaznici chteli treba vlastni font u konkretniho textu, vsem ostatnim 100+ to bylo jedno
- samozrejme, ze prvnim krokem byl refactoring a vytvoreni spolecnehop rozhrani a jeho implementace
- druhym krokem rozsireni spolecneho rozhrani o nove vlastnosti
- tretim krokem bylo odvozeni rozhrani od toho spolecneho a vyhazeni vsech metod z rozhrani tak, aby implementovala jen to, co bylo pro danou customizaci

A bylo po onanyji a stal se z toho udrzovatelny soft  ;D

« Poslední změna: 26-01-2019, 09:55:21 od pf1957 »

Offline Delfin

  • Padawan
  • ******
  • Příspěvků: 1527
  • Karma: 61
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Vyborny priklad je to TObject.AfterContruction. Kdyby z toho udelali delegata, jaky overhead u kazde instance TObject by zbytecne zavedli ev. kdyby raisnuli exception (a tim vlastne simulovali to abstract), aby to nebylo prazdne, tak by to kazdy potomek TObject  musel prekryvat prazdnou metodou... To by byl blazinec k nepouziti.

Ten overhead volani je asi jediny argument, jenz me presvedcil k souhlasu. Jinak samozrejme implementace metod cizich interface (konkretne typu procedure, jelikoz implementace function by vzdy mela vratit hodnotu). Chapu, ze jde o deklaraci "volitelne implementace" metody, nicmene urcite bych (pokud bych na realnou situaci narazil) minimalne vyemitoval kompilacni varovani (pripadne hint).
« Poslední změna: 26-01-2019, 23:25:08 od Delfin »
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Offline Ondřej Pokorný

  • Guru
  • *****
  • Příspěvků: 798
  • Karma: 59
    • Verze Delphi: Primárně Lazarus, jinak D7 až aktuální
    • Kluug.net
Já mám ještě dvě hezké:

Kód: Delphi [Vybrat]
  1. constructor TObject.Create;
  2. begin
  3. end;
  4.  
  5. destructor TObject.Destroy;
  6. begin
  7. end;
Embarcadero Technology Partner

Offline Delfin

  • Padawan
  • ******
  • Příspěvků: 1527
  • Karma: 61
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Já mám ještě dvě hezké:

Kód: Delphi [Vybrat]
  1. constructor TObject.Create;
  2. begin
  3. end;
  4.  
  5. destructor TObject.Destroy;
  6. begin
  7. end;

Dobra, jen bych prosil vysveteleni, proc bych mel pro vlastni tridu deklarovat metodu (tedy typu procedure, constructor a destructor), jenz bude prazdna?
I'm a soldier, so don't panic! I know the underground! I like WTFPL license! No more Google, go duck, go!

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 3833
  • Karma: 35
    • Verze Delphi: XE7 professional
Lebo ju občas budem potrebovať a nechcem stratiť možnosť vždy použiť inherited. Kvôli automatizácii spúšťania rutín.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2398
  • Karma: 129
    • Verze Delphi: D2007, XE3, DX10
Dobra, jen bych prosil vysveteleni, proc bych mel pro vlastni tridu deklarovat metodu (tedy typu procedure, constructor a destructor), jenz bude prazdna?
To je furt dokola: proste pri analyze a navrhu rozhrani vypadne, ze pro nektere tridy potrebujes nejakou operaci, ktera je vazana na nejakou logiku spolecnou vsem tem tridam, pricemz pocet tech trid neni dopredu znamy a neni konecny. Samozrejme bys to mohl matlat kondicionalem v run-time a operaci volat jen v pozadovanych pripadech. Ale OOP nam nabizi polymorfismus, ktery umoznuje s ruznymi objekty 'anonymne' manipulovat pres jejich spolecne rozhrani.

A to rozhrani muzes vytvorit:
- dedicnosti vystavenim rozhrani spolecne tridy a jeho dedenim/prekryvanim
- kompozici nadefinovanim extra rozhrani a jeho implementaci v kazde instanci
- kombinaci obeho.

Takze je otazka, pro co se rozhodnes:
- u dedicnosti v bazalni tride implementujes prevazujici stav tj. treba NIC
- u kompozice by jsi stav musel explicitne implementovat u kazde implementace rozhrani. Takze tam ti NIC tj. prazdna metoda nevadi  :o ?

BTW, nevim, proc se ti do hlavy zakousla zrovna prazdna procedure, protoze to je jen metoda implementujici nejake implicitni chovani a je uplne jedno, jestli je void nebo ne - podle toho co pises, tak ti zrejme function nevadi  :o

O konstruktorech/destruktorech nechci diskutovat, protoze jejich vlastnosti maji v ruznych jazykach ruzne vlastnosti a nema to tudiz obecnou platnost.

 

S rychlou odpovědí můžete používat BB kódy a emotikony jako v běžném okně pro odpověď, ale daleko rychleji.

Jméno: E-mail:
Ověření:
Kolik je šest plus čtyři (slovem):