Véglegesítő - Finalizer
A számítástechnikában a véglegesítő vagy a véglegesítési módszer egy speciális módszer, amely elvégzi a véglegesítést , általában a tisztítás valamilyen formáját. A véglegesítőt az objektum megsemmisítése során , az objektum elosztása előtt hajtják végre , és kiegészíti az inicializálót , amelyet az objektum létrehozása során hajtanak végre , az allokációt követően . Egyesek a véglegesítőket erősen elbátortalanítják a megfelelő használat nehézségei és az általuk hozzáadott bonyolultság miatt, és helyettük alternatívákat javasolnak, elsősorban az ártalmatlanítási mintát - lásd a véglegesítőkkel kapcsolatos problémákat .
A "véglegesítő" kifejezést elsősorban objektum-orientált és funkcionális nyelveken használják , amelyek szemétgyűjtést használnak , amelyek archetípusa a Smalltalk . Ez ellentétben áll a " destruktorral ", amely olyan módszer, amelyet véglegesítésre hívnak fel a determinisztikus objektum élettartamú nyelvekben, archetipikusan C ++ . Ezek általában kizáróak - egy nyelvnek vagy véglegesítői vannak (ha automatikusan szemetet gyűjtenek), vagy destruktorok (ha manuálisan kezelik a memóriát), de ritka esetekben egy nyelvnek mindkettője lehet, például a C ++ / CLI és D , valamint referenciaszámlálás esetén (a szemétszállítás nyomon követése helyett) a terminológia változó. A technikai használatban a "véglegesítő" a destruktorokra is utalhat, mivel ezek véglegesítést is végeznek, és néhány finomabb megkülönböztetést vonnak le - lásd a terminológiát . A "végleges" kifejezést egy olyan osztály megjelölésére is használják, amely nem örökölhető ; ez nem függ össze.
Terminológia
A "véglegesítő" és a "véglegesítés", valamint a "romboló" és a "rombolás" terminológiája a szerzők között változó, és néha nem egyértelmű.
A megszokott értelemben a destruktor az objektum megsemmisítésénél determinisztikusan nevezett módszer, az archetípus pedig C ++ destruktor; míg a véglegesítőt a szemétgyűjtő nem determinisztikusan hívja, az archetípus pedig Java finalize módszer.
Azoknál a nyelveknél, amelyek referenciaszámlálással valósítják meg a szemétgyűjtést , a terminológia változó, egyes nyelvek, például az Objective-C és a Perl a "destructor" -ot, más nyelvek, például a Python pedig a "finalizer" -et használják (specifikációnként a Python szemetet gyűjt, de a referencia A CPython implementáció, mivel a 2.0-s verziója a referenciaszámlálás és a szemétgyűjtés kombinációját használja). Ez azt a tényt tükrözi, hogy a referenciaszámlálás féldeterminisztikus objektum-élettartamot eredményez: azoknál az objektumoknál, amelyek nem részei egy ciklusnak, az objektumok determinisztikusan megsemmisülnek, amikor a referenciaszám nullára csökken, de a ciklus részét képező objektumok nem-determinisztikusan pusztulnak el. , a szemétszállítás külön formájának részeként.
Bizonyos szűk technikai használatban a "konstruktor" és a "destruktor" nyelv szintű kifejezések, vagyis "osztályban meghatározott módszerek", míg az "inicializáló" és a "véglegesítő" megvalósítási szintű kifejezések, vagyis "objektum létrehozása során meghívott módszerek", vagy megsemmisítés". Így például a C # nyelv eredeti specifikációja "destruktorokra" hivatkozott, annak ellenére, hogy a C # szemetet gyűjt, de a Közös Nyelvi Infrastruktúra (CLI) specifikációja és futásidejű környezete mint Common Language Runtime (CLR) megvalósítása ), a "véglegesítők" -re hivatkozva. Ezt tükrözik a C # nyelvi bizottság feljegyzései, amelyek részben így szólnak: "A C # fordító a destruktorokat fordítja ... [valószínűleg] példány véglegesítő [k] re. Ez a terminológia zavaró, ezért a C # specifikáció újabb verziói a véglegesítőként hivatkoznak a nyelvi szintű módszerre.
Egy másik nyelv, amely nem különbözteti meg ezt a terminológiát, a D. Bár a D osztályok szemetet gyűjtenek, tisztítási funkcióikat destruktoroknak nevezik.
Használat
A véglegesítést elsősorban takarításra, memória vagy más erőforrások felszabadítására használják: a kézi memóriakezeléssel lefoglalt memória elosztására ; a referenciák törlése, ha referenciaszámlálást alkalmaznak (csökkenési referenciaszámok); erőforrások felszabadítása, különösen az erőforrás-beszerzési kezdeményezés (RAII) idiómájában; vagy egy objektum regisztrációjának törléséhez. A véglegesítés mértéke nyelvenként jelentősen eltér, a kiterjedt véglegesítéstől kezdve a C ++ nyelven, amelynek kézi memóriakezelése, referenciaszámlálása és determinisztikus objektum-élettartama van; gyakran nem véglegesítik a Java-ban, amelynek objektum-élettartama nem determinisztikus, és amelyet gyakran nyomkövető szemétgyűjtővel valósítanak meg. Az is lehetséges, hogy kevés vagy egyáltalán nem (kifejezetten a felhasználó által megadott) véglegesítés, de jelentős implicit véglegesítés történik a fordító, tolmács vagy futás közben; ez általános az automatikus referenciaszámlálás esetén, például a Python CPython referencia-implementációjában, vagy az Object -C Apple megvalósításának automatikus referenciaszámlálásában, amelyek a véglegesítés során automatikusan megszakítják a referenciákat. A véglegesítő tetszőleges kódot tartalmazhat; egy különösen összetett felhasználás az objektum automatikus visszaadása egy objektumkészletbe .
A memória elosztása a véglegesítés során olyan nyelvekben gyakori, mint a C ++, ahol a kézi memóriakezelés szabványos, de a kezelt nyelvekben is előfordul, ha a memóriát a kezelt kupacon kívül osztják ki (külsőleg a nyelvhez); a Java-ban ez a Java Native Interface (JNI) és ByteBuffer az új I / O (NIO) objektumokkal történik . Ez utóbbi problémákat okozhat, mivel a szemétszedő nem tudja követni ezeket a külső erőforrásokat, ezért nem lesznek elég agresszívan összegyűjtve, és memóriahiányos hibákat okozhatnak a nem kezelt memória kimerülése miatt - ez elkerülhető az őslakosok kezelésével. memória, mint erőforrás, és a dispose mintát használja , az alábbiakban leírtak szerint.
A véglegesítők általában sokkal kevésbé szükségesek és sokkal kevésbé használatosak, mint a destruktorok. Sokkal kevésbé szükségesek, mert a szemétgyűjtés automatizálja a memóriakezelést , és sokkal kevésbé használják, mert általában nem determinisztikusan hajtják végre őket - előfordulhat, hogy nem hívják őket időben, sőt egyáltalán nem, és a végrehajtási környezetet nem lehet megjósolni - és így bármilyen A determinisztikus módon történő tisztítást ehelyett valamilyen más módszerrel kell elvégezni, leggyakrabban manuálisan az ártalmatlanítási mintán keresztül . Nevezetesen, mind a Java, mind a Python nem garantálja, hogy a véglegesítőket valaha is meghívják, és így nem lehet rájuk hivatkozni a tisztítás során.
Mivel a programozó nem tudja ellenőrizni a végrehajtásukat, általában a legkevésbé triviális műveleteknél ajánlatos kerülni a véglegesítőket. Különösen a destruktorokban gyakran végrehajtott műveletek általában nem megfelelőek a véglegesítők számára. Gyakori anti-minta az, hogy a véglegesítőket úgy írják, mintha rombolók lennének, ami felesleges és hatástalan is, a véglegesítők és a destruktorok közötti különbségek miatt. Ez különösen gyakori a C ++ programozók körében , mivel a destruktorokat erősen használják az idiomatikus C ++ rendszerben, az erőforrás-beszerzés kezdeményezése (RAII) után.
Szintaxis
A véglegesítőket használó programozási nyelvek: C ++ / CLI , C # , Clean , Go , Java és Python . A szintaxis nyelvenként jelentősen eltér.
A Java-ban a véglegesítő egy úgynevezett módszer finalize , amely felülírja a Object.finalize módszert.
A Pythonban a véglegesítő egy úgynevezett módszer __del__ .
A Perlben a véglegesítő egy ún DESTROY .
A C # nyelven a véglegesítő (a szabvány korábbi verzióiban "destructor" -nak nevezik) egy olyan módszer, amelynek neve az osztálynév ~ előtaggal, mint a ~Foo - ez ugyanaz a szintaxis, mint egy C ++ destructor , és ezeket a módszereket eredetileg "destruktoroknak" hívták. ", a C ++ analógiájára, annak ellenére, hogy eltérő magatartást tanúsítottak, de az általa okozott zavartság miatt" véglegesítőknek "nevezték át.
A destruktorokkal és véglegesítőkkel egyaránt rendelkező C ++ / CLI-ben a destructor olyan módszer, amelynek neve az osztálynév ~ előtaggal, mint a ~Foo (mint a C # -ben), a véglegesítő pedig egy olyan módszer, amelynek neve az osztálynév ! előtaggal, mint ben !Foo .
A Go programban a véglegesítőket egyetlen mutatóra alkalmazzák a runtime.SetFinalizer függvény meghívásával a standard könyvtárban.
Végrehajtás
A véglegesítőt akkor hívják meg, amikor az objektumot szeméttel gyűjtik össze - miután egy objektum szemétté vált (elérhetetlen), de még mielőtt a memóriája el lett osztva. A véglegesítés nem determinisztikusan, a szemétgyűjtő döntése alapján történik, és soha nem fordulhat elő. Ez ellentétben áll a destruktorokkal, amelyeket determinisztikusan hívnak meg, amint egy objektum már nincs használatban, és mindig meghívják őket, kivéve a program kontrollálatlan leállítását. A véglegesítők leggyakrabban példányos módszerek , mivel objektum-specifikus műveletekre van szükség.
A szemétszedőnek számolnia kell a tárgy feltámadásának lehetőségével is. Leggyakrabban ezt úgy hajtják végre, hogy először véglegesítőket hajtanak végre, majd ellenőrzik, hogy valamilyen tárgyat feltámasztottak-e, és ha igen, megszakítják azok megsemmisítését. Ez a további ellenőrzés potenciálisan drága - egy egyszerű megvalósítás újra ellenőrzi az összes szemetet, ha egyetlen objektumnak is van véglegesítője -, így mindkettő lelassítja és bonyolítja a szemétszállítást. Emiatt a véglegesítõket tartalmazó objektumokat ritkábban lehet összegyûjteni, mint a véglegesítõket nem tartalmazó objektumokat (csak bizonyos ciklusokban), ami súlyosbítja az azonnali véglegesítésre való támaszkodásból eredõ problémákat, például az erõforrások szivárgását.
Ha egy tárgyat feltámasztanak, akkor felmerül a további kérdés, hogy a véglegesítőt újra meghívják-e, amikor legközelebb megsemmisítik - a destruktorokkal ellentétben a véglegesítőket potenciálisan többször is meghívják. Ha a véglegesítőket feltámasztott tárgyakra hívják fel, az objektumok ismételten feltámadhatják magukat és elpusztíthatatlanok lehetnek; ez a Python 3.4 Python előtti CPython-implementációjában és a CLR nyelvekben, például a C # -ben fordul elő. Ennek elkerülése érdekében sok nyelven, beleértve a Java-t, az Objective-C-t (legalábbis az Apple legújabb megvalósításaiban) és a Python-t a Python 3.4-ből, az objektumok legfeljebb egyszer véglegesülnek, ami nyomon követést igényel, ha az objektum még véglegesítve van.
Más esetekben, különös tekintettel a CLR nyelvekre, mint például a C #, a véglegesítést külön az objektumoktól követik nyomon, és az objektumokat többször is regisztrálhatják vagy visszavonhatják a véglegesítéshez.
Problémák
A véglegesítők jelentős számú problémát okozhatnak, ezért számos hatóság erőteljesen elkeseríti őket. Ezek a problémák a következők:
- A véglegesítőket nem lehet időben vagy egyáltalán nem hívni, ezért nem lehet rájuk támaszkodni, hogy fenntartják az állapotot, felszabadítsák a szűkös erőforrásokat, vagy bármi más fontosat tegyenek.
- A véglegesítők objektum feltámadását eredményezhetik , ami gyakran programozási hiba, és amelynek lehetősége jelentősen lelassítja és bonyolítja a szemétszállítást.
- A véglegesítőket szemétgyűjtés alapján futtatják, amely általában a kezelt memória nyomására épül - más erőforráshiány esetén nem működnek, és így nem alkalmasak más szűkös erőforrások kezelésére.
- A véglegesítők nem meghatározott sorrendben futnak, és nem támaszkodhatnak osztály invariánsaira (mivel utalhatnak más, már véglegesített objektumokra).
- A lassú véglegesítők késleltethetik a többi véglegesítőt.
- A véglegesítőkön belüli kivételeket általában nem lehet kezelni, mert a véglegesítő nem meghatározott környezetben fut, és vagy figyelmen kívül hagyható, vagy a program kontrollálatlan leállítását okozhatja.
- A véglegesítők hivatkozhatnak és véletlenül véglegesíthetik az élő objektumokat, megsértve ezzel a program invariánsait.
- A véglegesítők szinkronizálási problémát okozhatnak, különben is, szekvenciális (egyszálas) programokban, mivel a véglegesítés egyidejűleg (konkrétan, egy vagy több külön szálban) történhet.
- A véglegesítők holtpontot okozhatnak, ha szinkronizációs mechanizmusokat, például zárakat használnak, mivel nem meghatározott sorrendben futnak, és esetleg egyidejűleg futnak.
- A program befejezése során futtatott véglegesítők nem támaszkodhatnak a szokásos futási környezetre, ezért téves feltételezések miatt kudarcot vallhatnak - ezért a véglegesítők gyakran nem futnak a felmondás során.
Továbbá, a véglegesítők nem tudnak futni, mivel az objektumok túl elérhetőek maradnak, amikor várhatóan szemétnek számítanak, akár programozási hibák, akár váratlan elérhetőség miatt. Például, amikor a Python kivételt fog (vagy ha egy interaktív módban nincs kivétel), akkor hivatkozást tart arra a veremkeretre, ahol a kivétel felmerült, ami életben tartja az adott veremkeretről hivatkozott objektumokat.
A szuperosztály véglegesítői lassíthatják az alosztály szemétgyűjtését is, mivel a véglegesítő potenciálisan az alosztály mezőire utalhat, és így a mező nem lehet a következő ciklusig gyűjtött szemét, miután a véglegesítő futott. Ez elkerülhető az öröklés helyett a kompozíció alkalmazásával .
Erőforrás menedzsment
Gyakori anti-minta az, hogy a véglegesítők segítségével erőforrásokat bocsátanak ki, a C ++ erőforrás-beszerzési kezdeményezés (RAII) kifejezésével analóg módon : szerezzen be egy erőforrást az inicializálóban (konstruktor), és engedje el a véglegesítőben (destruktor). Ez számos okból nem működik. Alapvetően a véglegesítőket soha nem lehet meghívni, és még akkor is, ha hívják, nem lehet időben felhívni őket - így a véglegesítők felhasználása az erőforrások felszabadítására általában erőforrásszivárgást okoz . A véglegesítőket nem hívják előírt sorrendben, míg az erőforrásokat gyakran meghatározott sorrendben kell felszabadítani, gyakran az ellenkező sorrendben, amelyben megszerezték őket. Továbbá, mivel a véglegesítőket a szemétgyűjtő döntése alapján hívják meg, gyakran csak felügyelt memória nyomáson hívják őket (amikor kevés a kezelt memória), függetlenül az erőforrás nyomásától - ha a szűkös erőforrásokat a szemét tartja, de rengeteg van A rendelkezésre álló kezelt memória hiányában előfordulhat, hogy nem történik szemétszállítás, így nem igényelheti ezeket az erőforrásokat.
Így ahelyett, hogy véglegesítőket használna az automatikus erőforrás-kezeléshez, a szeméttel összegyűjtött nyelveken az embernek manuálisan kell kezelnie az erőforrásokat, általában az ártalmatlanítási minta használatával . Ebben az esetben az erőforrások még beszerezhetők az inicializálóban, amelyet kifejezetten az objektum példányosításakor hívnak meg, de a dispos módszerben felszabadítják. A dispose módszert kifejezetten vagy hallgatólagosan meg lehet hívni olyan nyelvi konstrukciókkal, mint a C # using , a Java try -erőforrásokkal vagy a Python with .
Bizonyos esetekben azonban mind az elidegenítési mintát, mind a véglegesítőket használják az erőforrások felszabadítására. Ez elsősorban olyan CLR nyelveken található meg, mint például a C #, ahol a véglegesítést biztonsági másolatként használják: amikor egy erőforrást megszereznek, akkor a megszerző objektumot sorba állítják a véglegesítéshez, hogy az erőforrás objektum megsemmisítésekor felszabaduljon, még akkor is, ha az erőforrás nem kézi ártalmatlanítással szabadon engedi.
Determinisztikus és nem determinisztikus objektum élettartamok
A determinisztikus objektum-élettartamú nyelveken, nevezetesen a C ++ nyelven, az erőforrás-kezelést gyakran úgy hajtják végre, hogy az erőforrás-birtok élettartamát az objektum élettartamához kötik, erőforrásokat szereznek az inicializálás során és felszabadítják azokat a véglegesítés során; ezt Resource Acquisition Is Initialization (RAII) néven ismerjük . Ez biztosítja, hogy az erőforrás-birtoklás osztályinvariáns , és az erőforrások azonnal felszabaduljanak, amikor az objektum megsemmisül.
Azonban a nem determinisztikus objektum-élettartamú nyelveken - amelyek az összes főbb szemétgyűjtő nyelvet magukban foglalják (például C #, Java és Python) - ez nem működik, mert a véglegesítés nem biztos, hogy időben vagy egyáltalán nem történik meg, és ezáltal előfordulhat, hogy sokáig vagy egyáltalán nem szabadul fel, ami erőforrásszivárgást okoz . Ezekben a nyelvekben az erőforrásokat általában manuálisan kezelik a dispose minta segítségével : az erőforrásokat még inicializáláskor megszerezhetjük, de egy dispose módszer meghívásával szabadíthatjuk fel őket . Mindazonáltal a véglegesítés használata ezeken a nyelveken az erőforrások felszabadításához általános anti-minta , és a hívás elfelejtése dispose továbbra is erőforrás-szivárgást okoz.
Bizonyos esetekben mindkét technikát kombinálják, explicit dispose módszer alkalmazásával, de a véglegesítés során még mindig meglévő erőforrásokat is felszabadítanak biztonsági mentésként. Ez általában megtalálható a C # -ban, és úgy valósítják meg, hogy egy objektumot regisztrálnak véglegesítésre, amikor egy erőforrást megszereznek, és elnyomják a véglegesítést, amikor egy erőforrás felszabadul.
Tárgy feltámadása
Ha a felhasználó által megadott véglegesítők engedélyezettek, akkor a véglegesítés objektum feltámadását okozhatja , mivel a véglegesítők tetszőleges kódot futtathatnak, ami élő objektumokról hivatkozásokat hozhat létre a megsemmisített objektumokra. A szemétszedés nélküli nyelvek esetében ez súlyos hiba, és lógó hivatkozásokat és memóriabiztonsági megsértéseket okoz ; a szemétszedéssel rendelkező nyelveknél ezt megakadályozza a szemétszedő, leggyakrabban egy újabb lépéssel hozzáadva a szemétszállításhoz (az összes felhasználó által megadott véglegesítő futtatása után ellenőrizze a feltámadást), ami bonyolítja és lassítja a szemétszállítást.
A tárgy feltámadása azt is jelenti, hogy egy tárgy nem pusztulhat el, és kóros esetekben egy objektum a véglegesítés során mindig feltámadhat, elpusztíthatatlanná téve magát. Ennek megakadályozása érdekében egyes nyelvek, például a Java és a Python (a Python 3.4-ből), csak egyszer véglegesítik az objektumokat, és nem véglegesítik a feltámadott objektumokat. Konkrétan ez követéssel történik, ha egy objektum objektumonként véglegesítésre került. Az Objective-C is hasonló okokból követi a véglegesítést (legalábbis a legújabb Apple verziókban), hibaként kezelve a feltámadást.
Más megközelítést alkalmaznak a .NET-keretrendszerben , nevezetesen a C # és a Visual Basic .NET , ahol a véglegesítést az objektum helyett "sor" követi nyomon. Ebben az esetben, ha egy felhasználó által megadott véglegesítőt biztosítunk, akkor az objektum alapértelmezés szerint csak egyszer véglegesül (a létrehozáskor a véglegesítéshez sorban van, és a véglegesítés után le lesz távolítva), de ez a GC modul meghívásával megváltoztatható . A véglegesítést meg lehet akadályozni hívással GC.SuppressFinalize , amely leköti az objektumot, vagy újraaktiválható GC.ReRegisterForFinalize az objektumot lehívó hívással. Ezeket különösen akkor használják, ha a véglegesítést erőforrás-menedzsmentként használják az ártalmatlanítási minta kiegészítéseként, vagy egy objektumkészlet megvalósításakor .
Kontraszt az inicializálással
A véglegesítés formailag kiegészíti az inicializálást - az inicializálás az élettartam elején, a véglegesítés a végén történik, de a gyakorlatban jelentősen eltér. Mind a változókat, mind az objektumokat inicializálják, elsősorban az értékek hozzárendeléséhez, de általában csak az objektumokat véglegesítik, és általában nincs szükség értékek törlésére - a memóriát egyszerűen az operációs rendszer képes lefoglalni és visszanyerni.
A kezdeti értékek hozzárendelésén túl az inicializálást elsősorban erőforrások megszerzésére vagy egy szolgáltatás regisztrálására használják valamilyen szolgáltatással (például egy eseménykezelővel ). Ezeknek a műveleteknek szimmetrikus felszabadítási vagy regisztráció-visszavonási műveleteik vannak, és ezeket szimmetrikusan kezelhetjük egy véglegesítőben, ami RAII-ban történik. Azonban sok nyelven, nevezetesen a szemétszállítással rendelkezőknél, az objektum élettartama aszimmetrikus: az objektum létrehozása determinisztikusan történik a kód valamely kifejezett pontján, de az objektum megsemmisítése nem determinisztikusan, valamilyen meghatározatlan környezetben, a szemétszedő belátása szerint történik. Ez az aszimmetria azt jelenti, hogy a véglegesítést nem lehet hatékonyan használni az inicializálás kiegészítéseként, mert ez nem időben, meghatározott sorrendben vagy meghatározott környezetben történik. A szimmetria részben helyreáll azáltal, hogy az objektumot egy meghatározott ponton is elhelyezi, de ebben az esetben az ártalmatlanítás és a megsemmisítés nem ugyanazon a ponton történik, és egy tárgy "eldobott, de még élő" állapotban lehet, ami gyengíti az osztályt invariáns és bonyolítja a felhasználást.
A változókat általában életük kezdetén inicializálják, de élettartamuk végén nem véglegesítik - bár ha egy változó értéke objektum, akkor az objektum véglegesíthető. Bizonyos esetekben a változók is véglegesítésre kerülnek: a GCC kiterjesztések lehetővé teszik a változók véglegesítését.
Kapcsolat finally
Amint azt az elnevezés is tükrözi, a "véglegesítés" és a finally konstrukció egyaránt hasonló célokat tölt be: valamilyen végső művelet végrehajtása, általában takarítás, miután valami más befejeződött. Különböznek abban az esetben, amikor előfordulnak - egy finally záradék akkor kerül végrehajtásra, amikor a program végrehajtása elhagyja a társított try záradék törzsét - ez a verem kikapcsolása során következik be, és így finally sorban van egy sor függőben lévő záradék -, míg a véglegesítés akkor történik, amikor egy objektum megsemmisül, ami a memóriakezelési módszer függvényében történik, és általában egyszerűen vannak olyan objektumok, amelyek véglegesítésre várnak - gyakran a kupacon -, amelyeknek nem kell külön sorrendben történniük.
Bizonyos esetekben azonban ezek egybeesnek. A C ++ - ban az objektum pusztulása determinisztikus, és egy finally klauzula viselkedését úgy lehet előállítani, hogy lokális változó van, amelynek értéke egy objektum, amelynek hatóköre blokk, és egy try záradék törzsének felel meg - az objektum véglegesítve (megsemmisül), amikor a végrehajtás kilép ebből a körből, pontosan mintha finally záradék lenne. Emiatt a C ++ - nak nincs finally konstrukciója - az a különbség, hogy a véglegesítést az osztálydefinícióban destruktorként definiálják, nem pedig a hívás helyén egy finally záradékban.
Ezzel ellentétben, finally egy coroutine-ban lévő klauzula esetében , hasonlóan a Python-generátorhoz, a coroutine soha nem szűnik meg - csak mindig megadva -, és így a szokásos végrehajtáskor a finally clause soha nem kerül végrehajtásra. Ha valaki egy koroutin példányait objektumként értelmezi, akkor a finally záradék az objektum véglegesítőjének tekinthető, és így akkor hajtható végre, amikor a példány szemetet gyűjt. A Python-terminológiában a coroutine definíciója generátorfüggvény , míg egy példánya generátorrendező , és így finally a generátorfüggvény egy mondata véglegesítővé válik ebből a függvényből példázott generátor iterátorokban.
Történelem
A véglegesítés, mint az objektum pusztításának külön lépése, Montgomery (1994) fogalmára datálódik , az analógia alapján a tárgyépítés inicializálásának korábbi megkülönböztetésével (Martin & Odell (1992)) . Az ezt megelőző irodalom ebben a folyamatban "megsemmisítést" használt, nem különböztetve meg a véglegesítést és az elosztást, és az erre az időszakra nyúló programozási nyelvek, mint a C ++ és a Perl, a "megsemmisítés" kifejezést használják. A "véglegesítés" és a "véglegesítés" kifejezéseket a Design Patterns (1994) befolyásos könyvében is használják . A Java 1995-ös bevezetése olyan finalize módszereket tartalmazott, amelyek népszerűsítették a kifejezést és összefüggésbe hozták a szemétszállítással, és a nyelvek ettől a ponttól kezdve általában ezt a különbséget teszik, és a "véglegesítés" kifejezést használják, különösen a szemétszállítás összefüggésében.
Lásd még
- Szemétgyűjtés , különös tekintettel a determinizmusra
- Tárgy élettartama
- Inicializálási folyamat és a kapcsolódó inicializáló minta
Megjegyzések
Hivatkozások
További irodalom
- Jagger, Jon; Perry, Nigel; Sestoft, Peter (2007). Jegyzetelt C # Standard . Morgan Kaufmann. ISBN 978-0-12-372511-0 .
- Martin, James; Odell, James J. (1992). Objektum-orientált elemzés és tervezés . Prentice-Hall. ISBN 978-0-13-630245-2 .
- Montgomery, Stephen (1994). Objektum-orientált informatika: elemzés, tervezés és megvalósítás . Academic Press. ISBN 978-0-12-505040-1 .
Külső linkek
- " Véglegesítés a megfelelő romboló helyett ", WikiWikiWeb - a Java véglegesítők összehasonlítása a C ++ destruktorokkal
- Paul Krill " Oracle ajánlja axing Java objektum véglegesítő " JavaWorld március 29, 2017.