In computer science, reflective programming or reflection is the ability of a process to examine, introspect, and modify its own structure and behavior. [1]
The earliest computers were programmed in their native assembly languages, which were inherently reflective, as these original architectures could be programmed by defining instructions as data and using self-modifying code. As the bulk of programming moved to higher-level compiled languages such as Algol, Cobol, Fortran, Pascal, and C, this reflective ability largely disappeared until new programming languages with reflection built into their type systems appeared.[ citation needed ]
Brian Cantwell Smith's 1982 doctoral dissertation introduced the notion of computational reflection in procedural programming languages and the notion of the meta-circular interpreter as a component of 3-Lisp. [2] [3]
Reflection helps programmers make generic software libraries to display data, process different formats of data, perform serialization and deserialization of data for communication, or do bundling and unbundling of data for containers or bursts of communication.
Effective use of reflection almost always requires a plan: A design framework, encoding description, object library, a map of a database or entity relations.
Reflection makes a language more suited to network-oriented code. For example, it assists languages such as Java to operate well in networks by enabling libraries for serialization, bundling and varying data formats. Languages without reflection such as C are required to use auxiliary compilers for tasks like Abstract Syntax Notation to produce code for serialization and bundling.
Reflection can be used for observing and modifying program execution at runtime. A reflection-oriented program component can monitor the execution of an enclosure of code and can modify itself according to a desired goal of that enclosure. This is typically accomplished by dynamically assigning program code at runtime.
In object-oriented programming languages such as Java, reflection allows inspection of classes, interfaces, fields and methods at runtime without knowing the names of the interfaces, fields, methods at compile time. It also allows instantiation of new objects and invocation of methods.
Reflection is often used as part of software testing, such as for the runtime creation/instantiation of mock objects.
Reflection is also a key strategy for metaprogramming.
In some object-oriented programming languages such as C# and Java, reflection can be used to bypass member accessibility rules. For C#-properties this can be achieved by writing directly onto the (usually invisible) backing field of a non-public property. It is also possible to find non-public methods of classes and types and manually invoke them. This works for project-internal files as well as external libraries such as .NET's assemblies and Java's archives.
A language that supports reflection provides a number of features available at runtime that would otherwise be difficult to accomplish in a lower-level language. Some of these features are the abilities to:
These features can be implemented in different ways. In MOO, reflection forms a natural part of everyday programming idiom. When verbs (methods) are called, various variables such as verb (the name of the verb being called) and this (the object on which the verb is called) are populated to give the context of the call. Security is typically managed by accessing the caller stack programmatically: Since callers() is a list of the methods by which the current verb was eventually called, performing tests on callers()[0] (the command invoked by the original user) allows the verb to protect itself against unauthorised use.
Compiled languages rely on their runtime system to provide information about the source code. A compiled Objective-C executable, for example, records the names of all methods in a block of the executable, providing a table to correspond these with the underlying methods (or selectors for these methods) compiled into the program. In a compiled language that supports runtime creation of functions, such as Common Lisp, the runtime environment must include a compiler or an interpreter.
Reflection can be implemented for languages without built-in reflection by using a program transformation system to define automated source-code changes.
Reflection may allow a user to create unexpected control flow paths through an application, potentially bypassing security measures. This may be exploited by attackers. [4] Historical vulnerabilities in Java caused by unsafe reflection allowed code retrieved from potentially untrusted remote machines to break out of the Java sandbox security mechanism. A large scale study of 120 Java vulnerabilities in 2013 concluded that unsafe reflection is the most common vulnerability in Java, though not the most exploited. [5]
The following code snippets create an instance foo
of class Foo
and invoke its method PrintHello
. For each programming language, normal and reflection-based call sequences are shown.
The following is an example in Common Lisp using the Common Lisp Object System:
(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)))
The following is an example in C#:
// Without reflectionvarfoo=newFoo();foo.PrintHello();// With reflectionObjectfoo=Activator.CreateInstance("complete.classpath.and.Foo");MethodInfomethod=foo.GetType().GetMethod("PrintHello");method.Invoke(foo,null);
This Delphi and Object Pascal example assumes that a TFoo class has been declared in a unit called Unit1:
usesRTTI,Unit1;procedureWithoutReflection;varFoo:TFoo;beginFoo:=TFoo.Create;tryFoo.Hello;finallyFoo.Free;end;end;procedureWithReflection;varRttiContext:TRttiContext;RttiType:TRttiInstanceType;Foo:TObject;beginRttiType:=RttiContext.FindType('Unit1.TFoo')asTRttiInstanceType;Foo:=RttiType.GetMethod('Create').Invoke(RttiType.MetaclassType,[]).AsObject;tryRttiType.GetMethod('Hello').Invoke(Foo,[]);finallyFoo.Free;end;end;
The following is an example in eC:
// Without reflectionFoofoo{};foo.hello();// With reflectionClassfooClass=eSystem_FindClass(__thisModule,"Foo");Instancefoo=eInstance_New(fooClass);Methodm=eClass_FindMethod(fooClass,"hello",fooClass.module);((void(*)())(void*)m.function)(foo);
The following is an example in Go:
import"reflect"// Without reflectionf:=Foo{}f.Hello()// With reflectionfT:=reflect.TypeOf(Foo{})fV:=reflect.New(fT)m:=fV.MethodByName("Hello")ifm.IsValid(){m.Call(nil)}
The following is an example in Java:
importjava.lang.reflect.Method;// Without reflectionFoofoo=newFoo();foo.hello();// With reflectiontry{Objectfoo=Foo.class.getDeclaredConstructor().newInstance();Methodm=foo.getClass().getDeclaredMethod("hello",newClass<?>[0]);m.invoke(foo);}catch(ReflectiveOperationExceptionignored){}
The following is an example in JavaScript:
// Without reflectionconstfoo=newFoo()foo.hello()// With reflectionconstfoo=Reflect.construct(Foo)consthello=Reflect.get(foo,'hello')Reflect.apply(hello,foo,[])// With evaleval('new Foo().hello()')
The following is an example in Julia:
julia>structPointx::Intyend# Inspection with reflectionjulia>fieldnames(Point)(:x, :y)julia>fieldtypes(Point)(Int64, Any)julia>p=Point(3,4)# Access with reflectionjulia>getfield(p,:x)3
The following is an example in Objective-C, implying either the OpenStep or Foundation Kit framework is used:
// Foo class.@interfaceFoo : NSObject-(void)hello;@end// Sending "hello" to a Foo instance without reflection.Foo*obj=[[Fooalloc]init];[objhello];// Sending "hello" to a Foo instance with reflection.idobj=[[NSClassFromString(@"Foo")alloc]init];[objperformSelector:@selector(hello)];
The following is an example in Perl:
# Without reflectionmy$foo=Foo->new;$foo->hello;# orFoo->new->hello;# With reflectionmy$class="Foo"my$constructor="new";my$method="hello";my$f=$class->$constructor;$f->$method;# or$class->$constructor->$method;# with evaleval"new Foo->hello;";
The following is an example in PHP: [6]
// Without reflection$foo=newFoo();$foo->hello();// With reflection, using Reflections API$reflector=newReflectionClass("Foo");$foo=$reflector->newInstance();$hello=$reflector->getMethod("hello");$hello->invoke($foo);
The following is an example in Python:
# Without reflectionobj=Foo()obj.hello()# With reflectionobj=globals()["Foo"]()getattr(obj,"hello")()# With evaleval("Foo().hello()")
The following is an example in R:
# Without reflection, assuming foo() returns an S3-type object that has method "hello"obj<-foo()hello(obj)# With reflectionclass_name<-"foo"generic_having_foo_method<-"hello"obj<-do.call(class_name,list())do.call(generic_having_foo_method,alist(obj))
The following is an example in Ruby:
# Without reflectionobj=Foo.newobj.hello# With reflectionobj=Object.const_get("Foo").newobj.send:hello# With evaleval"Foo.new.hello"
The following is an example using Xojo:
' Without reflectionDimfooInstanceAsNewFoofooInstance.PrintHello' With reflectionDimclassInfoAsIntrospection.Typeinfo=GetTypeInfo(Foo)Dimconstructors()AsIntrospection.ConstructorInfo=classInfo.GetConstructorsDimfooInstanceAsFoo=constructors(0).InvokeDimmethods()AsIntrospection.MethodInfo=classInfo.GetMethodsForEachmAsIntrospection.MethodInfoInmethodsIfm.Name="PrintHello"Thenm.Invoke(fooInstance)EndIfNext
JavaScript, often abbreviated as JS, is a programming language and core technology of the Web, alongside HTML and CSS. 99% of websites use JavaScript on the client side for webpage behavior.
Common Intermediate Language (CIL), formerly called Microsoft Intermediate Language (MSIL) or Intermediate Language (IL), is the intermediate language binary instruction set defined within the Common Language Infrastructure (CLI) specification. CIL instructions are executed by a CIL-compatible runtime environment such as the Common Language Runtime. Languages which target the CLI compile to CIL. CIL is object-oriented, stack-based bytecode. Runtimes typically just-in-time compile CIL instructions into native code.
Generic programming is a style of computer programming in which algorithms are written in terms of data types to-be-specified-later that are then instantiated when needed for specific types provided as parameters. This approach, pioneered in the programming language ML in 1973, permits writing common functions or data types that differ only in the set of types on which they operate when used, thus reducing duplicate code.
A dynamic programming language is a type of programming language that allows various operations to be determined and executed at runtime. This is different from the compilation phase. Key decisions about variables, method calls, or data types are made when the program is running, unlike in static languages, where the structure and types are fixed during compilation. Dynamic languages provide flexibility. This allows developers to write more adaptable and concise code.
In computing, type introspection is the ability of a program to examine the type or properties of an object at runtime. Some programming languages possess this capability.
Metaprogramming is a computer programming technique in which computer programs have the ability to treat other programs as their data. It means that a program can be designed to read, generate, analyse, or transform other programs, and even modify itself, while running. In some cases, this allows programmers to minimize the number of lines of code to express a solution, in turn reducing development time. It also allows programs more flexibility to efficiently handle new situations with no recompiling.
In computer programming, run-time type information or run-time type identification (RTTI) is a feature of some programming languages that exposes information about an object's data type at runtime. Run-time type information may be available for all types or only to types that explicitly have it. Run-time type information is a specialization of a more general concept called type introspection.
In some programming languages, eval
, short for evaluate, is a function which evaluates a string as though it were an expression in the language, and returns a result; in others, it executes multiple lines of code as though they had been included instead of the line including the eval
. The input to eval
is not necessarily a string; it may be structured representation of code, such as an abstract syntax tree, or of special type such as code
. The analog for a statement is exec, which executes a string as if it were a statement; in some languages, such as Python, both are present, while in other languages only one of either eval
or exec
is.
This article compares two programming languages: C# with Java. While the focus of this article is mainly the languages and their features, such a comparison will necessarily also consider some features of platforms and libraries.
In computing, late binding or dynamic linkage—though not an identical process to dynamically linking imported code libraries—is a computer programming mechanism in which the method being called upon an object, or the function being called with arguments, is looked up by name at runtime. In other words, a name is associated with a particular operation or object at runtime, rather than during compilation. The name dynamic binding is sometimes used, but is more commonly used to refer to dynamic scope.
In class-based, object-oriented programming, a constructor is a special type of function called to create an object. It prepares the new object for use, often accepting arguments that the constructor uses to set required member variables.
The syntax of Java is the set of rules defining how a Java program is written and interpreted.
In computer programming, an entry point is the place in a program where the execution of a program begins, and where the program has access to command line arguments.
In object-oriented programming, a factory is an object for creating other objects; formally, it is a function or method that returns objects of a varying prototype or class from some method call, which is assumed to be new. More broadly, a subroutine that returns a new object may be referred to as a factory, as in factory method or factory function. The factory pattern is the basis for a number of related software design patterns.
In the Java programming language, the final
keyword is used in several contexts to define an entity that can only be assigned once.
this, self, and Me are keywords used in some computer programming languages to refer to the object, class, or other entity which the currently running code is a part of. The entity referred to thus depends on the execution context. Different programming languages use these keywords in slightly different ways. In languages where a keyword like "this" is mandatory, the keyword is the only way to access data and methods stored in the current object. Where optional, these keywords can disambiguate variables and functions with the same name.
Oxygene is a programming language developed by RemObjects Software for Microsoft's Common Language Infrastructure, the Java Platform and Cocoa. Oxygene is based on Delphi's Object Pascal, but also has influences from C#, Eiffel, Java, F# and other languages.
Vala is an object-oriented programming language with a self-hosting compiler that generates C code and uses the GObject system.
C# 4.0 is a version of the C# programming language that was released on April 11, 2010. Microsoft released the 4.0 runtime and development environment Visual Studio 2010. The major focus of C# 4.0 is interoperability with partially or fully dynamically typed languages and frameworks, such as the Dynamic Language Runtime and COM.
Objective-C is a high-level general-purpose, object-oriented programming language that adds Smalltalk-style message passing (messaging) to the C programming language. Originally developed by Brad Cox and Tom Love in the early 1980s, it was selected by NeXT for its NeXTSTEP operating system. Due to Apple macOS’s direct lineage from NeXTSTEP, Objective-C was the standard language used, supported, and promoted by Apple for developing macOS and iOS applications from 1997, when Apple purchased NeXT until the introduction of the Swift language in 2014.