Feldolgozása az absztrakt módszerek Delphi

Az Object Pascal nyelv által használt Delphi fejlesztői környezet, van egy olyan mechanizmus virtuális konstruktőrök. Rajongói C ++ úgy tűnik, egy szörnyű eretnekség, de a virtuális konstruktőrök igen praktikusak a példányok létrehozása osztályok, amelyek nem határozzák meg lefordítani a generált kódot. Ez a technológia lehetővé teszi a fejlesztési komponens kódot anélkül, hogy végre egy osztály gyári.







A másik oldala az ezt a rugalmasságot az a képesség, hogy véletlenszerűen egy példányának létrehozásához egy absztrakt osztály, amely aztán csaknem elkerülhetetlenül vezet a hívást az egyik absztrakt módszerek. Ha a C ++ hívja tisztán virtuális függvény megköveteli a tisztességes mennyiségű készség, és gyakorlatilag lehetetlen, hogy neki hirtelen, Delphi, ezt úgy érjük el egy óvatlan mozgását. Sajnos, a beépített Delphi mechanizmusainak felderítése és feldolgozásának elméleti módszerek, hogy csak minimális információt a hiba forrását.

Virtuális konstruktőrök

Az összes példa ebben a cikkben, hacsak másként nem jelezzük, állítottak össze, és teszteltük Borland Delphi 5.

Az együtt arra az alkatrészre hivatkozunk osztály:

Ez lehetővé teszi, hogy hozzon létre olyan alkatrészek, utalva az osztály, akkor is, ha fejlett fordítása után a következő kódot:

Ez a lehetőség egy kulcsfontosságú az olvasás formái a mechanizmus DFM-fájlokat és erőforrásokat. Ezen kívül hasznos lehet a felhasználói kódot, amely közvetlenül nem kapcsolódik a VCL. A legnépszerűbb alkalmazásokat, mint funkcionalitás - ez az objektum sorozatprogramozásának regisztrációs plug-in. Ezen túlmenően, ez alapján mechanizmus és RTTI a Delphi 6 webszolgáltatások végrehajtását.

absztrakt módszerek

Nézzük a következő kódot:

Első pillantásra, minden rendben. Van egy absztrakt osztály, amely kijelenti, bizonyos funkciók, és egy leszármazottja, amely megvalósítja ezt a funkciót. Azt javasoljuk, hogy ezt így:

(Az aktuális kód, természetesen, sokkal bonyolultabb. Valószínűleg a tárgyak jön létre, egy helyen és használt másik, de a lényeg nem változik.)

Mi a probléma? És hogy gondatlan alkalmazása programozó könnyen közvetíteni mi eljárást paraméterként egy hivatkozás egy absztrakt osztály:

Ez a kód össze elég jól. Mi történik a futás? Egy egyszerű kísérlet azt mutatja, hogy az eredmény az lesz kibocsátó EAbstractError kizárás hívás esetén DoSomeJob módszer.

Úgy tűnik, hogy minden rendben van: az elkövető fogott, az igazság már helyreállították. De nem. EAbstractError - feltűnően nem informatív osztályban. Ő nem adott semmilyen információt a kontextus és az a hiba okát. Ha - a fejlesztő és az alkalmazás létrehozza a megfelelő üzenetet, akkor van esélye, hogy egy kis időt, hogy kommunikálni a hibakereső és átléphető fogni a jogsértő osztályban. De ha össze a könyvtár hibakeresési információk nélkül, valamint a forráskódot, az alkalmazás programozó csak a csoda mit csinált rosszul.

Vannak, persze, egy nagyon egyszerű módja annak, hogy „kap körül” a probléma - nem nyilvánítja elvont módszereket. VCL használja az „üres” módszer, egész idő alatt. Azonban nem ez az út az igazi programozók. Legalábbis az oka, hogy az „üres” a végrehajtási eljárások még mindig van némi értelme, de minden olyan funkciót kell vissza értéket.

Egy több természetes módja az, hogy tiltani példányosításához absztrakt osztályok, ahogy az, például a C ++. Sajnos, Delphi fordító korlátozott figyelmeztetés: „építési osztály példánya ... tartalmazó elméleti módszerekkel”. Ez a figyelmeztetés elnyomható a megfelelő fordítási beállításokat.

Általános szabály, hogy tiszta programozók szorosan figyelemmel kíséri a figyelmeztetést adott ki a fordító. De a fent leírt helyzet, a „villámcsapás” és okainak megkeresztelt programozó nem fog.

teszt alkalmazás

Mi használatát illusztrálja a technika jellemzője az objektum modell Object Pascal a példa egy egyszerű alkalmazást.

A program nagyon egyszerű. Ez lehetővé teszi a felhasználó számára, hogy belépjen két egész, és azokat egy sor egyszerű számtani műveleteket. A végrehajtás csak a program az összeadás és a szorzás jön, de akkor győződjön meg arról, hogy a programozók segítségével a felhasználók a program lépést tartani a korral, a fejlődő dugó.







A teszt a koncepció, akkor hozzon létre egy kiegészítő csomag, amely végre két osztály komplex egész szereplők: TPowerOp - teljesítmény üzemeltető és TCnkOp - üzemeltető a kombinációk száma.

Osztályba TCnkOp mi „elfelejti”, hogy blokkolja az egyik absztrakt metódusnak egy alap osztályt. Látjuk, hogy a standard kezelés az ilyen hibák nem ad semmilyen információt a hiba okát, és a kivitelezést a feldolgozás, így azonnal meghatározni, hogy mely osztály, amely eljárás elvetették elvont.

További információ

Ha szeretne többet megtudni, hogy mi vezetett az absztrakt hívást, akkor kell foglalkozni, hogy hogyan valósítja Delphi absztrakt kezelési módszerek.

Normál felvezető

Ha nyomozni hívja absztrakt módszer TAbstractObject.DoSomeJob, kiderül egy érdekes adat: a vezérlés átkerül a rendszer eljárás _AbstractError:

Továbbfejlesztett processzor

Ebből két következtetést lehet levonni az előző részben:

  1. Van dokumentált módon, hogy regisztrálja a kezelő meghívja a kivonatot.
  2. Annak ellenére, hogy a közeg nem megy át ezen a felvezető paramétereket, funkciók, amelyek felhívják a kezelő nem befolyásolja a hívó.

Jegyezze fel a kódot TAbstractHandler.HandleAbstract eljárás - ez kivételt dob ​​az osztály nevét, mint egy szöveges üzenetet. Első pillantásra úgy tűnik, hogy mindig visszatér a string „TAbstractHandler”, de ez nem az. Az a tény, hogy hívják TAbstractHandler.HandleAbstract módszer egy tárgy teljesen más osztály! Tény, hogy a kódon, amely nagyon hasonló:

Ilyen kivétel tartalmaz a szöveg „TAbstractObject”. Általában ezek a hívások hibához vezet, de bizonyos szabályok, ezek teljesen biztonságos. „Pesszimista” változata ezeknek a szabályoknak a következő: hívja az „idegen” módszer csak akkor használható, ha a rendszer csak a mezők és módszerek közös őse a „saját” és az „idegen” osztályú. A gyakorlatban több szabadságot, de a mi esetünkben ez már elég. HandleAbstract módszer egyetlen módszer ClassName kapható TObject, amely garantáltan az őse minden Delphi osztályok.

Ez a technika nem működik, ha hív egy absztrakt módszer osztályban. A osztály módszerek önálló utal, hogy a osztály, nem egy tárgy, és használt a helyettesítés nem megfelelő. Sajnos, megbízható módon kell kezelni ezt, nem látom - elég nehéz megkülönböztetni egy mutatót a VMT a mutatót a mutatót VMT.

korai előrejelzésén

Hogy megakadályozzák az példányainak absztrakt osztályok, szükséges mindenekelőtt, hogy válaszoljon a kérdésre: „Ez egy absztrakt osztály?”. A válasz erre a kérdésre egyszerű: „absztrakt osztály, ha nem tartalmaz elméleti módszerekkel.” Delphi önmagában nincs beépített eszközök ellenőrzési módszerek az absztrakt, így az alapok kell kitalálni ezeket magad.

Annak kiderítésére, hogy egy osztály módszer elméleti, meg kell ásni egy kicsit a sötét mélységekbe A rendszer modul segítségével egy lépésben. Mint már tudjuk az előző részben, egy kísérlet, hogy okozhat absztrakt módszer vezet minket _AbstractError eljárást. Most arra van szükség, hogy nyomon követni az utat, amely elvezet az eljárást.

Tanulmányok virtuális módszer tábla szerkezete (VMT), amelyet a fordító, és RTTI általában érdekes folyamat, amely eltarthat egy nagyon szórakoztató kíváncsi fejlesztő. Azok számára, akik nem akarnak időt pazarolni előkészítő rendszer Delphi kódot, azt bemutatni az adatokat kész állapotban.

Szerkezete Delphi osztályok

  • Hasonlítsa össze a hivatkozás az osztályt, hogy teszteljék az objektum típusát.
  • Calling osztály módszerek.
  • Hívás konstruktőrök.

Sajnos, ez a funkció nem elég keresni az absztrakt módszereket. Ehhez a keresési meg kell nézni „a motorháztető alatt” osztály - nevezetesen, hogy milyen a TObject.ClassType módszer. Végrehajtás, természetesen változhat verziójukban. A Delphi 5 kód rendkívül szűkszavú:

Milyen érdekes! Néhány ezek közül kevesebb, mint nulla. Ítélve nevük állandók amíg vmtAfterConstruction (offset -28) pointerek található különböző érdekes adatokat. Aztán ott vannak a mutatók virtuális metódusnak TObject: AfterConstruction, BeforeDestruction, Diszpécser DefaultHandler, NewInstance, FreeInstance, elpusztítani. Aztán vannak olyan módszerek, a nem negatív korrekciót. Így a mutató található elején a hivatkozott objektum valahol „középen» VMT. És ez azt jelenti - pontosan az a hely, ahol lesz található virtuális metódusnak leszármazott osztályokban. VmtQueryInterface nevének állandók, vmtAddRef és vmtRelease világos, miért tette - egyébként TObject leszármazottai lehetetlen lett volna végrehajtani IUnknown felület.

Tehát 4 bájt, kapott egy hívást TObject.ClassType, pont a táblázat tetején virtuális metódusnak leszármazottai TObject. Ezt a következtetést lehet tekinteni „biztonságos”, ameddig Delphi támogatja az együttműködést COM.

absztrakt módszerek

Ez a kód némi magyarázatot igényel.

Kap egy mutatót osztály módszer a változó TAP, akkor válassza ki belőle egy mutatót a kódot a dokumentált csökkentést SysUtils.TMethod típusát.

Azonban ezeket a kísérleteket végeztek egy osztály, állítsák össze, mint része a kérelmet. A példánkban az osztály egy külön csomagot összeállítani egy külön fájlba könyvtárban. Lesz kihívás, ha ugyanazt a _AbstractProc ezen osztályok? És ha igen, hogyan?

meg kell tudni, hogyan hajtja végre Delphi dynamic link alkatrészek csomagokat a választ ezekre a kérdésekre. A részletes vizsgálata a téma túlmutat ezt a cikket. Ezért azonnal adja az eredményt ide, kihagyva a leírást a kutatás .bpl-fájlokat.

Igen, Delphi szigorúan be annak érdekében, hogy az alkalmazás nem lehetett betölteni két változatban azonos modul különböző csomagokat. Azaz, biztosak lehetünk abban, hogy minden elméleti kihívás vezet minket egy _AbstractProc. Ehhez, akkor használja a mechanizmus import táblázatok által biztosított formátum a Windows PE-fájlokat. A gyakorlatban ez azt jelenti, hogy a megfelelő pozíciót a VMT jelzi a kódrészletet (thunk) a következő: