Reflexe (počítačové programování) - Reflection (computer programming)
v počítačová věda, reflexní programování je schopnost a proces zkoumat, introspekt a upravovat vlastní strukturu a chování.[1]
Historické pozadí
Nejstarší počítače byly naprogramovány ve svém rodném jazyce montážní jazyky, které byly neodmyslitelně reflexní, protože tyto původní architektury mohly být programovány definováním pokynů jako dat a použitím samočinně se měnící kód. Jak se programování přesunulo do kompilovaných jazyků vyšší úrovně, jako je Algol, Cobol, a Fortran (ale také Pascal a C a mnoho dalších jazyků), tato reflexní schopnost do značné míry zmizela, dokud se neobjevily programovací jazyky s odrazem zabudovaným do jejich typových systémů.[Citace je zapotřebí ]
Brian Cantwell Smith doktorská disertační práce z roku 1982[2][3] zavedl pojem výpočetní reflexe v procedurálním programovací jazyky a pojem metakruhový tlumočník jako součást 3-Lisp.
Použití
Reflexe pomáhá programátorům vytvářet obecné softwarové knihovny pro zobrazení dat, zpracování různých formátů dat a provádění serializace nebo deserializace dat pro komunikaci, nebo proveďte seskupení a oddělení dat pro kontejnery nebo shluky komunikace.
Efektivní využití odrazu téměř vždy vyžaduje plán: Konstrukční rámec, popis kódování, knihovna objektů, mapa databáze nebo vztahy entit.
Díky reflexi je jazyk vhodnější pro síťově orientovaný kód. Například pomáhá jazykům, jako je Java, dobře fungovat v sítích tím, že umožňuje knihovnám serializaci, sdružování a různé datové formáty. Jazyky bez reflexe (např. C ) musí používat pomocné překladače, např. pro Anotace abstraktní syntaxe, k výrobě kódu pro serializaci a sdružování.
Reflexi lze použít k pozorování a úpravě provádění programu za běhu. Reflexně orientovaná programová komponenta může sledovat provádění přílohy kódu a může se upravit podle požadovaného cíle souvisejícího s touto přílohou. Toho se obvykle dosahuje dynamickým přiřazováním programového kódu za běhu.
V objektově orientovaných programovacích jazycích, jako je Jáva, reflexe umožňuje inspekce tříd, rozhraní, polí a metod za běhu bez znalosti názvů rozhraní, polí, metod v době kompilace. Také to umožňuje instance nových objektů a vyvolání metod.
Reflexe se často používá jako součást testování softwaru, například pro vytvoření / vytvoření instance modulu runtime falešné předměty.
Reflexe je také klíčovou strategií pro metaprogramování.
V některých objektově orientovaných programovacích jazycích, například C# a Jáva, odraz lze použít k obejití přístupnost členů pravidla. U C # -properties toho lze dosáhnout zápisem přímo do (obvykle neviditelného) záložního pole neveřejné vlastnosti. Je také možné najít neveřejné metody tříd a typů a ručně je vyvolat. To funguje pro interní soubory projektu i externí knihovny (.Net-assemblies a Java-archive).
Implementace
Reflexe podporující jazyk poskytuje řadu funkcí dostupných za běhu, které by jinak bylo obtížné dosáhnout v jazyce nižší úrovně. Některé z těchto funkcí jsou schopnosti:
- Objevte a upravte konstrukce zdrojového kódu (například bloky kódu, třídy, metody, protokoly atd.) jako prvotřídní objekty za běhu.
- Převést a tětiva shoda symbolického názvu třídy nebo funkce s odkazem na nebo vyvolání dané třídy nebo funkce.
- Vyhodnoťte řetězec, jako by to byl příkaz zdrojového kódu za běhu.
- Vytvořte nového tlumočníka pro bajtový kód jazyka, který dá nový význam nebo účel programovací konstrukci.
Tyto funkce lze implementovat různými způsoby. v BUČENÍ, reflexe je přirozenou součástí každodenního programovacího idiomu. Při volání sloves (metod) se používají různé proměnné, jako např sloveso (název volaného slovesa) a tento (objekt, na kterém je sloveso voláno) jsou vyplněna, aby poskytla kontext volání. Zabezpečení se obvykle spravuje programovým přístupem k zásobníku volajícího: Od volající() je seznam metod, kterými bylo aktuální sloveso nakonec voláno, při provádění testů volající() [0] (příkaz vyvolaný původním uživatelem) umožňuje slovesu chránit se před neoprávněným použitím.
Zkompilované jazyky spoléhají na svůj běhový systém, aby poskytly informace o zdrojovém kódu. Zkompilovaný Cíl-C spustitelný soubor například zaznamenává názvy všech metod do bloku spustitelného souboru a poskytuje tabulku, která jim odpovídá se základními metodami (nebo selektory pro tyto metody) kompilovanými do programu. V kompilovaném jazyce, který podporuje běhové vytváření funkcí, jako je Společný Lisp, běhové prostředí musí obsahovat kompilátor nebo tlumočníka.
Reflexe může být implementována pro jazyky, které nemají vestavěné reflexní zařízení, pomocí a transformace programu systém definovat automatizované změny zdrojového kódu.
Příklady
Následující fragmenty kódu vytvoří instance foo
z třída Foo
a vyvolat jeho metoda Ahoj
. Pro každého programovací jazyk, jsou zobrazeny normální a reflexní volací sekvence.
C#
Následuje příklad v C#:
// Bez odrazuFoo foo = Nový Foo();foo.Ahoj();// S odrazemObjekt foo = Aktivátor.CreateInstance(„complete.classpath.and.Foo“);MethodInfo metoda = foo.GetType().GetMethod("Tisk Ahoj");metoda.Vyvolat(foo, nula);
Delphi
Tento Delphi příklad předpokládá, že a TFoo třída byla deklarována v jednotce s názvem Lekce 1:
používá RTTI, Lekce 1;postup Bez odrazu;var Foo: TFoo;začít Foo := TFoo.Vytvořit; Snaž se Foo.Ahoj; Konečně Foo.Volný, uvolnit; konec;konec;postup WithReflection;var RttiContext: TRttiContext; RttiType: TRttiInstanceType; Foo: TObject;začít RttiType := RttiContext.NajítTyp('Unit1.TFoo') tak jako TRttiInstanceType; Foo := RttiType.GetMethod('Vytvořit').Vyvolat(RttiType.MetaclassType, []).AsObject; Snaž se RttiType.GetMethod('Ahoj').Vyvolat(Foo, []); Konečně Foo.Volný, uvolnit; konec;konec;
eC
Následuje příklad v eC:
// Bez odrazuFoo foo { };foo.Ahoj();// S odrazemTřída fooClass = eSystem_FindClass(__thisModule, "Foo");Instance foo = eInstance_New(fooClass);Metoda m = eClass_FindMethod(fooClass, "Ahoj", fooClass.modul);((prázdnota (*)())(prázdnota *)m.funkce)(foo);
Jít
Následuje příklad v Jít:
import "odrážet"// Bez odrazuF := Foo{}F.Ahoj()// S odrazemfT := odrážet.Typ(Foo{})F v := odrážet.Nový(fT)m := F v.MethodByName("Ahoj")-li m.Je platný() { m.Volání(nula)}
Jáva
Následuje příklad v Jáva:
import java.lang.reflect.Method;// Bez odrazuFoo foo = Nový Foo();foo.Ahoj();// S odrazemSnaž se { Objekt foo = Foo.třída.novýInstance(); Metoda m = foo.getClass().getDeclaredMethod("Ahoj", Nový Třída<?>[0]); m.vyvolat(foo);} chytit (ReflectiveOperationException ignorováno) {}
Cíl-C
Následuje příklad v Cíl-C, což znamená buď OpenStep nebo Foundation Kit rámec se používá:
// Foo třída.@rozhraní Foo : NSObject- (prázdnota)Ahoj;@konec// Odeslání „ahoj“ instanci Foo bez odrazu.Foo *obj = [[Foo alokace] inic];[obj Ahoj];// Odeslání „ahoj“ instanci Foo s odrazem.id obj = [[NSClassFromString(@ „Foo“) alokace] inic];[obj performSelector: @volič(Ahoj)];
Perl
Následuje příklad v Perl:
# Bez odrazumůj $ foo = Foo->Nový;$ foo->Ahoj;# neboFoo->Nový->Ahoj;# S odrazemmůj $ třída = "Foo"můj $ konstruktor = "Nový";můj $ metoda = "Ahoj";můj $ f = $ třída->$ konstruktor;$ f->$ metoda;# nebo$ třída->$ konstruktor->$ metoda;# s evaleval „new Foo-> ahoj;“;
PHP
Následuje příklad v PHP:
// Bez odrazu$ foo = Nový Foo();$ foo->Ahoj();// S reflexí pomocí Reflections API$ reflektor = Nový ReflectionClass('Foo');$ foo = $ reflektor->novýInstance();$ ahoj = $ reflektor->getMethod('Ahoj');$ ahoj->vyvolat($ foo);
Krajta
Následuje příklad v Krajta:
# Bez odrazuobj = Foo()obj.Ahoj()# S odrazemobj = globálové()["Foo"]()getattr(obj, "Ahoj")()# S evaleval("Foo (). Ahoj ()")
R
Následuje příklad v R:
# Bez odrazu, za předpokladu, že foo () vrátí objekt typu S3, který má metodu „ahoj“obj <- foo()Ahoj(obj)# S odrazemtřída <- "foo"metoda <- "Ahoj"obj <- do.call(třída, seznam())do.call(metoda, seznam(obj))
Rubín
Následuje příklad v Rubín:
# Bez odrazuobj = Foo.Novýobj.Ahoj# S odrazemjméno třídy = "Foo"název_metody = :Ahojobj = Objekt.const_get(jméno třídy).Novýobj.poslat název_metody# S evaleval „Foo.new.hello“
Xojo
Následuje příklad použití Xojo:
"Bez reflexe."Ztlumit fooInstance Tak jako Nový FoofooInstance.Ahoj"S odrazem."Ztlumit classInfo Tak jako Introspekce.Typeinfo = GetTypeInfo(Foo)Ztlumit konstruktéři() Tak jako Introspekce.ConstructorInfo = classInfo.GetConstructorsZtlumit fooInstance Tak jako Foo = konstruktéři(0).VyvolatZtlumit metody() Tak jako Introspekce.MethodInfo = classInfo.GetMethodsPro Každý m Tak jako Introspekce.MethodInfo v metody Li m.název = "Tisk Ahoj" Pak m.Vyvolat(fooInstance) Konec Lidalší
Viz také
- Seznam reflexních programovacích jazyků a platforem
- Zrcadlo (programování)
- Programovací paradigmata
- Vlastní hostování
- Samočinně se měnící kód
- Zadejte introspekci
- Typ
Reference
Citace
- ^ Výukový program pro behaviorální reflexi a jeho implementaci, autor: Jacques Malenfant et al. (PDF), neznámé, archivovány z originál (PDF) dne 21. srpna 2017, vyvoláno 23. června 2019
- ^ Brian Cantwell Smith, Procedurální reflexe v programovacích jazycích, Katedra elektrotechniky a informatiky, Massachusetts Institute of Technology, disertační práce, 1982.
- ^ Brian C. Smith. Reflexe a sémantika v procedurálním jazyce Archivováno 2015-12-13 na Wayback Machine. Technická zpráva MIT-LCS-TR-272, Massachusetts Institute of Technology, Cambridge, Massachusetts, leden 1982.
Zdroje
- Jonathan M. Sobel a Daniel P. Friedman. Úvod do programování zaměřeného na reflexi (1996), Indiana University.
- Antireflexní technika používající obálku C # a C ++ / CLI k zabránění zloděje kódu
Další čtení
- Ira R. Forman a Nate Forman, Java Reflection v akci (2005), ISBN 1-932394-18-4
- Ira R. Forman a Scott Danforth, Uvedení metaclass do práce (1999), ISBN 0-201-43305-2