Reflective programming
In computer science, reflective programming or reflection is the ability of a process to examine, introspect, and modify its own structure and behavior.
foo of
class (defclassfoo()())
(defmethodprint-hello((ffoo))(formatT"Hello from ~S~%"f))
;; Normal, without reflection
(let((foo(make-instance'foo)))
(print-hellofoo))
;; With reflection to look up the class named "foo" and the method
;; named "print-hello" that specializes on "foo".
(let*((foo-class(find-class(read-from-string"foo")))
(print-hello-method(find-method(symbol-function(read-from-string"print-hello"))
nil(listfoo-class))))
(funcall(sb-mop:method-generic-functionprint-hello-method)
(make-instancefoo-class)))
Reflection is not possible in C, though parts of reflection can be emulated.
\n#include <stdlib.h>\n#include <string.h>\n\ntypedef struct {\n // ...\n} Foo;\n\ntypedef void (*Method)(void*);\n\n// The method: Foo::printHello\nvoid Foo_printHello(void* _) {\n printf(\"Hello, world!\\n\");\n}\n\n// Simulated method table\ntypedef struct {\n const char* name;\n Method fn;\n} MethodEntry;\n\nconst MethodEntry FOO_METHODS[] = {\n { \"printHello\", Foo_printHello },\n { NULL, NULL } // Sentinel to mark end\n};\n\n// Simulate reflective method lookup\nMethod findMethodByName(const char* name) {\n for (size_t i = 0; FOO_METHODS[i].name; i++) {\n if (strcmp(FOO_METHODS[i].name, name) == 0) {\n return FOO_METHODS[i].fn;\n }\n }\n return NULL;\n}\n\nint main() {\n // Without reflection\n Foo foo;\n Foo_printHello(&foo);\n\n // With emulated reflection\n Foo* reflected = (Foo*)malloc(sizeof(Foo));\n if (!reflected) {\n fprintf(stderr, \"Memory allocation failed\\n\");\n return EXIT_FAILURE;\n }\n\n const char* name = \"printHello\";\n Method m = findMethodByName(name);\n\n if (m) {\n m(reflected);\n } else {\n fprintf(stderr, \"Method '%s' not found\\n\", name);\n free(reflected);\n return EXIT_FAILURE;\n }\n\n free(reflected);\n return EXIT_SUCCESS;\n}\n"}}'>#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedefstruct{
// ...
}Foo;
typedefvoid(*Method)(void*);
// The method: Foo::printHello
voidFoo_printHello(void*_){
printf("Hello, world!\n");
}
// Simulated method table
typedefstruct{
constchar*name;
Methodfn;
}MethodEntry;
constMethodEntryFOO_METHODS[]={
{"printHello",Foo_printHello},
{NULL,NULL}// Sentinel to mark end
};
// Simulate reflective method lookup
MethodfindMethodByName(constchar*name){
for(size_ti=0;FOO_METHODS[i].name;i++){
if(strcmp(FOO_METHODS[i].name,name)==0){
returnFOO_METHODS[i].fn;
}
}
returnNULL;
}
intmain(){
// Without reflection
Foofoo;
Foo_printHello(&foo);
// With emulated reflection
Foo*reflected=(Foo*)malloc(sizeof(Foo));
if(!reflected){
fprintf(stderr,"Memory allocation failed\n");
returnEXIT_FAILURE;
}
constchar*name="printHello";
Methodm=findMethodByName(name);
if(m){
m(reflected);
}else{
fprintf(stderr,"Method '%s' not found\n",name);
free(reflected);
returnEXIT_FAILURE;
}
free(reflected);
returnEXIT_SUCCESS;
}
The example below is in C++ (using reflection added in C++26).
\nconstexpr auto createInvokerImpl = [] -> auto {\n static constexpr info M = findMethod(Clazz, Name);\n static_assert(\n meta::parameters_of(M).size() == 0 && meta::return_type_of(M) == ^^void,\n \"Reflected method must take zero parameters and return void.\"\n );\n return []([:Clazz:]& instance) -> void { instance.[:M:](); };\n}();\n\nconsteval info createInvoker(info clazz, string_view name) {\n return meta::substitute(\n ^^createInvokerImpl,\n { meta::reflect_constant(clazz), meta::reflect_constant_string(name) }\n );\n}\n\nclass Foo {\nprivate:\n // ...\npublic:\n Foo() = default;\n\n void printHello() const {\n std::println(\"Hello, world!\");\n }\n};\n\nint main(int argc, char* argv[]) {\n Foo foo;\n\n // Without reflection\n foo.printHello();\n\n // Through splicing\n foo.[:findMethod(^^Foo, \"printHello\"):]();\n\n // Through invocation/template factory\n auto invokePrint = [:createInvoker(^^Foo, \"printHello\"):];\n invokePrint(foo);\n}\n"}}'>importstd;
usingstd::string_view;
usingstd::views::filter;
usingstd::meta::access_context;
usingstd::meta::exception;
usingstd::meta::info;
namespacemeta=std::meta;
constevalboolisNonstaticMethod(infomem)noexcept{
returnmeta::is_class_member(mem)&&
!meta::is_static_member(mem)&&
meta::is_function(mem);
}
constevalinfofindMethod(infoclazz,string_viewname){
for(infomember:meta::members_of(clazz,access_context::current())|filter(isNonstaticMethod)){
if(meta::has_identifier(member)&&meta::identifier_of(member)==name){
returnmember;
}
}
// Note: this is std::meta::exception, not std::exception
throwexception(std::format("Failed to retrieve method {} from class {}",name,meta::identifier_of(clazz)),^^findMethod);
}
template<infoClazz,constchar*Name>
constexprautocreateInvokerImpl=[]->auto{
staticconstexprinfoM=findMethod(Clazz,Name);
static_assert(
meta::parameters_of(M).size()==0&&meta::return_type_of(M)==^^void,
"Reflected method must take zero parameters and return void."
);
return[]([:Clazz:]&instance)->void{instance.[:M:]();};
}();
constevalinfocreateInvoker(infoclazz,string_viewname){
returnmeta::substitute(
^^createInvokerImpl,
{meta::reflect_constant(clazz),meta::reflect_constant_string(name)}
);
}
classFoo{
private:
// ...
public:
Foo()=default;
voidprintHello()const{
std::println("Hello, world!");
}
};
intmain(intargc,char*argv[]){
Foofoo;
// Without reflection
foo.printHello();
// Through splicing
foo.[:findMethod(^^Foo,"printHello"):]();
// Through invocation/template factory
autoinvokePrint=[:createInvoker(^^Foo,"printHello"):];
invokePrint(foo);
}
The example below is in C#:
usesRTTI,Unit1;
procedureWithoutReflection;
var
Foo:TFoo;
begin
Foo:=TFoo.Create;
try
Foo.Hello;
finally
Foo.Free;
end;
end;
procedureWithReflection;
var
RttiContext:TRttiContext;
RttiType:TRttiInstanceType;
Foo:TObject;
begin
RttiType:=RttiContext.FindType('Unit1.TFoo')asTRttiInstanceType;
Foo:=RttiType.GetMethod('Create').Invoke(RttiType.MetaclassType,[]).AsObject;
try
RttiType.GetMethod('Hello').Invoke(Foo,[]);
finally
Foo.Free;
end;
end;
The example below is in eC:
packageorg.wikipedia.examples;
importjava.lang.reflect.Method;
class Foo{
// ...
publicvoidprintHello(){
System.out.println("Hello, world!");
}
}
publicclass InvokeFooExample{
publicstaticvoidmain(String[]args){
// Without reflection
Foofoo=newFoo();
foo.printHello();
// With reflection
try{
FooreflectedFoo=Foo.class
.getDeclaredConstructor()
.newInstance();
Methodm=reflectedFoo
.getClass()
.getDeclaredMethod("printHello",newClass<?>[0]);
m.invoke(reflectedFoo);
}catch(ReflectiveOperationExceptione){
System.err.printf("An error occurred: %s%n",e.getMessage());
}
}
}
Java also provides an internal class (not officially in the Java Class Library) in module jdk.unsupported, sun.reflect.Reflection which is used by sun.misc.Unsafe. It contains one method, getCallerClass(int depth);"},"parts":[{"template":{"target":{"wt":"java","href":"./Template:Java"},"params":{"1":{"wt":"static Class<?> getCallerClass(int depth);"}},"i":0}}]}'>staticClass<?>getCallerClass(intdepth); for obtaining the class making a call at a specified depth. This is now superseded by using the class julia>struct Point
x::Int
y
end
# Inspection with reflection
julia>fieldnames(Point)
(:x, :y)
julia>fieldtypes(Point)
(Int64, Any)
julia>p=Point(3,4)
# Access with reflection
julia>getfield(p,:x)
3
Using Java reflection:
) {\n // Without reflection\n val foo = Foo()\n foo.printHello()\n\n // With reflection\n try {\n // Foo::class.java retrieves a java.lang.Class<Foo>\n val reflectedFoo = Foo::class.java\n .getDeclaredConstructor()\n .newInstance()\n\n val m: Method = reflectedFoo.javaClass\n .getDeclaredMethod(\"printHello\")\n\n m.invoke(reflectedFoo)\n } catch (e: ReflectiveOperationException) {\n System.err.printf(\"An error occurred: %s%n\", e.message)\n }\n}\n"}}'>packageorg.wikipedia.examples
importjava.lang.reflect.Method
classFoo{
// ...
constructor()
funprintHello(){
println("Hello, world!")
}
}
funmain(args:Array<String>){
// Without reflection
valfoo=Foo()
foo.printHello()
// With reflection
try{
// Foo::class.java retrieves a java.lang.Class<Foo>
valreflectedFoo=Foo::class.java
.getDeclaredConstructor()
.newInstance()
valm:Method=reflectedFoo.javaClass
.getDeclaredMethod("printHello")
m.invoke(reflectedFoo)
}catch(e:ReflectiveOperationException){
System.err.printf("An error occurred: %s%n",e.message)
}
}
Using pure Kotlin:
) {\n // Without reflection\n val foo = Foo()\n foo.printHello()\n\n // With reflection\n try {\n // Foo::class retrieves a kotlin.reflect.KClass<Foo>\n val kClass = Foo::class\n val reflectedFoo = kClass.createInstance()\n val function = kClass.functions.first { it.name == \"printHello\" }\n function.call(reflectedFoo)\n } catch (e: Exception) {\n System.err.printf(\"An error occurred: %s%n\", e.message)\n }\n}\n"}}'>packageorg.wikipedia.examples
importkotlin.reflect.full.createInstance
importkotlin.reflect.full.functions
classFoo{
// ...
funprintHello(){
println("Hello, world!")
}
}
funmain(args:Array<String>){
// Without reflection
valfoo=Foo()
foo.printHello()
// With reflection
try{
// Foo::class retrieves a kotlin.reflect.KClass<Foo>
valkClass=Foo::class
valreflectedFoo=kClass.createInstance()
valfunction=kClass.functions.first{it.name=="printHello"}
function.call(reflectedFoo)
}catch(e:Exception){
System.err.printf("An error occurred: %s%n",e.message)
}
}
The example below is in Objective-C, implying either the OpenStep or Foundation Kit framework is used:
hello;\";\n"}}'># Without reflection
my$foo=Foo->new;
$foo->hello;
# or
Foo->new->hello;
# With reflection
my$class="Foo"
my$constructor="new";
my$method="hello";
my$f=$class->$constructor;
$f->$method;
# or
$class->$constructor->$method;
# with eval
eval"new Foo->hello;";
The example below is in PHP:
hello();\n\n// With reflection, using Reflections API\n$reflector = new ReflectionClass(\"Foo\");\n$foo = $reflector->newInstance();\n$hello = $reflector->getMethod(\"hello\");\n$hello->invoke($foo);\n"}}'>// Without reflection
$foo = new Foo();
$foo->hello();
// With reflection, using Reflections API
$reflector = new ReflectionClass("Foo");
$foo = $reflector->newInstance();
$hello = $reflector->getMethod("hello");
$hello->invoke($foo);
The example below is in Python:
None:\n print(\"Hello, world!\")\n\nif __name__ == \"__main__\":\n # Without reflection\n obj: Foo = Foo()\n obj.print_hello()\n\n # With reflection\n obj: Foo = globals()[\"Foo\"]()\n _ = getattr(obj, \"print_hello\")()\n\n # With eval\n eval(\"Foo().print_hello()\")\n"}}'>classFoo:
# ...
defprint_hello(self) -> None:
print("Hello, world!")
if __name__ == "__main__":
# Without reflection
obj: Foo = Foo()
obj.print_hello()
# With reflection
obj: Foo = globals()["Foo"]()
_ = getattr(obj, "print_hello")()
# With eval
eval("Foo().print_hello()")
The example below is in R:
// A basic macro that registers a method name string to an actual method call
macro_rules!invoke_method{
($instance:expr,$method_name:expr)=>{
match$method_name{
"print_hello"=>$instance.print_hello(),
_=>eprintln!("An error occurred: Method not found."),
}
};
}
structFoo;
implFoo{
fnprint_hello(&self){
println!("Hello, world!");
}
}
fnmain(){
letfoo=Foo;
// Normal call sequence
foo.print_hello();
// Reflection-style sequence via compile-time mapping
letmethod_to_call="print_hello";
invoke_method!(foo,method_to_call);
}
Swift reflection is read-only, and thus dynamic invocation is only possible through Objective-C.
' Without reflection
DimfooInstanceAsNewFoo
fooInstance.PrintHello
' With reflection
DimclassInfoAsIntrospection.Typeinfo=GetTypeInfo(Foo)
Dimconstructors()AsIntrospection.ConstructorInfo=classInfo.GetConstructors
DimfooInstanceAsFoo=constructors(0).Invoke
Dimmethods()AsIntrospection.MethodInfo=classInfo.GetMethods
ForEachmAsIntrospection.MethodInfoInmethods
Ifm.Name="PrintHello"Then
m.Invoke(fooInstance)
EndIf
Next