Reflexe (programování)
Author
Albert FloresReflexe je v objektově orientovaném programování schopnost programovacího jazyka zjistit za běhu informace o určitém programovém objektu. Obecně v programování je reflexe schopnost zjistit informace o programu a jeho syntaktické struktuře.
V objektově orientovaném programování je program rozdělen do tříd, kdy jednotlivá třída popisuje vnitřní strukturu objektu a jeho vnější rozhraní. Na základně tříd je možné tvořit jednotlivé objekty. +more Některé jazyky mají schopnost za běhu zjistit informace o daném programu. Tato schopnost se nazývá reflexe, s jejíž pomocí lze získat za běhu programu informace o typu objektu. V objektově orientovaném programování se dá říci, že vše je objekt, tak je tedy objektem i třída a jiné datové typy, o kterých lze zjistit požadované informace.
Využití
Schopnost reflexe je vhodná pro vzdálené zpracování, kdy jsou dva počítače a na jeden z nich přicházejí objekty z toho druhého a počítač, který objekty zpracovává, má možnost získat pomocí reflexe potřebné informace o daném typu objektu. Lze to využít v jakémkoli programu, který za běhu upravuje své chování vůči objektům, se kterými pracuje.
Reflexe v Javě
Informace, které potřebujeme, můžeme získat z instance třídy java. lang. +moreClass. Tento class-objekt mají jak třídy, tak rozhraní i primitivní typy. Při zavádění daného typu do paměti je pomocí instance třídy ClassLoader vytvořen class-objekt, který lze využít při získávání informací o daném typu objektu. Pokud je nutné zajistit dynamické chování programu, v tomto případě je vhodnější využít jazyky jako Groovy, Jython, JRuby, jejichž překladače řeší dynamičnost pomocí reflexe. V případě, že se liší jednotlivé verze JVM svými knihovnami, pak je možné přizpůsobit chování programu verzi virtuálního stroje, na kterém aktuálně program běží.
Za běhu programu je možné získat: * Název typu * Druh typu (interface, třída, výčtový typ) * Anotace * Atributy, konstruktory, metody a vnořené datové typy
S těmito informacemi získanými za běhu programu je následně možné například volat konstruktory, metody nebo zjišťovat a přiřazovat hodnoty atributů. Lze také zjistit informace o nedostupných členech, ale v běžných situacích k nim není přístup.
Získání existujícího class-objektu
Pokud je typ daného názvu již zaveden do paměti, tak je vrácen jeho class-objekt a nevytváří se nový.
Pokud známe typ objektu a nemáme jeho instanci, pak literálem Typ. class private Class clazz = Color. +moreclass; Field [] fields = clazz. getDeclaredFields; //získání všech deklarovaných proměnných ze třídy.
U každého objektu lze volat metodu getClass, díky čemuž jsme schopni zjistit, jaké třídy je objekt instancí. Trida trida = new Trida; trida. +moregetReflection. getAnnotations; //získá anotace dané třídy.
Získání class-objektu datového typu zadaného svým názvem
Pomocí statické metody Class. forName(String) lze získat class-objekt typu se zadaným úplným názvem, tj. +more včetně názvu balíčku. Při použití modulů lze volánímClass. forName(Module, String) požádat o class-objekt zadaného typu v zadaném modulu. Rozšířené možnosti nabízí metoda Class. forName(String, boolean, ClassLoader), jejíž druhý parametr zadává, zda má být daný typ inicializován, a třetí parametru specifikuje ClassLoader, který má daný datový typ zavést. Class. forName("java. lang. String"); Class. forName("Foo",true,this. getClass. getClassLoader);.
Reflexní metody třídy Class v Javě
Třída Class definuje 71 metod, z toho jen 3 statické (forName(?));
Metody pro získání konstruktorů
Statický inicializátor (tj. konstruktor třídy) není možné získat. +more Získat lze pouze konstruktory instancí. Constructor getConstructor(Class. parameterTypes) Constructor getDeclaredConstructor(Class. parameterTypes).
Metody pro získání polí
U polí se zadává jenom název. Field getField(String name) Field getDeclaredField(String name)
Metody pro získaní metod
Method getMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException
Všechny veřejné metody včetně zděděných
Method[] getMethods throws SecurityException
Všechny s výjimkou zděděných
Method[] getDeclaredMethods throws SecurityException Metody pro získání názvu: String getSimpleName String getName String toString
Metody pro získání informací o daném druhu typu, reprezentovaném class-objektem
isAnnotation, isAnonymousClass, isArray, isEnum, isInterface, isLocalClass, isMemberClass, isPrimitive, isSynthetic
Ostatní informace o typu
getPackage, int getModifiers, Class getSuperclass, Class getComponentType
Metody vracející reprezentanty veřejných členů
Constructor[] getConstructors Field[] getFields Method[] getMethods Class[] getClasses Annotation[] getAnnotations
Metody vracející reprezentanty deklarovaných členů
Vrací soukromé členy, ale nevrací zděděné členy. Constructor[] getDeclaredConstructors Field[] getDeclaredFields Method[] getDeclaredMethods Class[] getDeclaredClasses Annotation[] getDeclaredAnnotations
Reflexe v C#
Jmenný prostor, který umožňuje v . NET používat reflexi se jmenuje System. +moreReflection. Základní cestou k metadatům typu v mechanismu reflexe je třída získat instanci třídy System. Type. Díky ní je možné získat rozličné informace o daném typu, včetně seznamu jeho členů. Může se tak udělat pomocí metody GetType nebo pomocí operátoru typeof. Type t = Type. GetType("System. Int32"); Type t2 = Type. GetType("MyNamespace. MyType", MyAssembly); Type t3 = typeof(System. Int32); Rozdíl mezi těmito dvěma druhy je v tom, že GetType se vyhodnocuje za běhu, zatímco operátor typem v době kompilace. Máme-li instanci třídy Type, máme přístup k metadatům, atributům nebo vytvářet nové instance typů. Vztahy mezi dědičnosti mezi reflexními typy . NET.
Ve chvíli, kdy máme odkaz na některý z těchto elementů, tak můžeme pohybovat se vztahy mezi daným elementem a souvisejícími prvky, jak je uvedeno na následujícím obrázku.
Nejzákladnějším typem reflexe je v . NET třída Type. +more Reprezentuje metadata pro jednotlivé deklarace typů v aplikaci. Typy obsahují členy. Ty zahrnují konstruktory, proměnné, vlastnosti, události a metody. Typy mohou navíc obsahovat vnořené typy, které se typicky používají jako pomocné třídy. Typy jsou seskupené do modulů a moduly jsou obsažené v sestavách.
Reflexe v PHP
Od 5. verze tohoto jazyka, kdy se přišlo s objekty, má PHP základní schopnost reflexe, avšak ne dostatečnou, proto se různé frameworky snaží o její rozšíření. +more O reflexi v tomto jazyce se stará třída Reflection. V základním PHP například nemůžeme zjistit nic o anotacích daného objektu.
$a = new A; $reflector = new ReflectionClass('A'); //vezme všechny vlastnosti třídy A a uloží je do pole $properties = $reflector->getProperties;
Nette
Nette\Object usnadňuje i přístup k sebereflexi třídy pomocí metody getReflection, která vrací objekt třídy ClassType.
$circle = new Circle; echo $circle->getReflection->hasMethod('getArea'); // existuje metoda 'getArea' ? echo $circle->getReflection->getName; // vrací název třídy, tj. 'Circle'
Zend
Zend_Reflection_Class dědí od základní třídy Reflection a přidává další funkčnost.
$r = new Zend_Reflection_Class($class); printf( "The class level docblock has the short description: %s\n". "The class level docblock has the long description:\n%s\n", $r->getDocblock->getShortDescription, $r->getDocblock->getLongDescription); // Get the declaring file reflection $file = $r->getDeclaringFile;
Reflexe v Objective-C
// Foo třída @interface Foo : NSObject - (void)hello; @end // bez reflexe Foo *obj = [[Foo alloc] init]; [obj hello]; // s reflexí id obj = [[NSClassFromString(@"Foo") alloc] init]; [obj performSelector: @selector(hello)];
Reflexe v Ruby
# bez reflexe obj = Foo.new obj.hello # s reflexí class_name = "Foo" method = :hello obj = Kernel.const_get(class_name).new obj.send method
Reflexe v Perlu
# bez reflexe my $foo = Foo->new; $foo->hello; # nebo Foo->new->hello;
s reflexí
my $class = "Foo" my $constructor = "new"; my $method = "hello"; my $f = $class->$constructor; $f->$method; # nebo $class->$constructor->$method;
Reflexe ve Visual Basic
' Využití GetType k získání informací o daném typu: Dim i As Integer = 42 Dim type As System. Type = i. +moreGetType System. Console. WriteLine(type) ' Využití reflexe k získání informací z Assembly: Dim info As System. Reflection. Assembly = GetType(System. Int32). Assembly System. Console. WriteLine(info) ' Využití GetType k získání informací o daném typu: Dim i As Integer = 42 Dim type As System. Type = i. GetType System. Console. WriteLine(type) ' Využití reflexe k získání informací z Assembly: Dim info As System. Reflection. Assembly = GetType(System. Int32). Assembly System. Console. WriteLine(info).