Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Type introspection
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
{{multiple issues| {{how-to|date=December 2011}} {{excessive examples|date=December 2011}} }} In [[computing]], '''type introspection''' is the ability of a program to ''examine'' the [[Data type|type]] or properties of an [[Object (computer science)|object]] at [[Run time (program lifecycle phase)|runtime]]. Some [[programming language]]s possess this capability. Introspection should not be confused with [[reflection (computer programming)|reflection]], which goes a step further and is the ability for a program to ''manipulate'' the metadata, properties, and functions of an object at runtime. Some programming languages also possess that capability (e.g., [[Java (programming language)|Java]], [[Python (programming language)|Python]], [[Julia (programming language)|Julia]], and [[Go (programming language)|Go]]). ==Examples== ===Objective-C=== In [[Objective-C]], for example, both the generic Object and NSObject (in [[Cocoa (API)|Cocoa]]/[[OpenStep]]) provide the [[method (computer science)|method]] {{code|isMemberOfClass:}} which returns true if the argument to the method is an instance of the specified class. The method {{code|isKindOfClass:}} analogously returns true if the argument inherits from the specified class. For example, say we have an {{code|Apple}} and an {{code|Orange}} class inheriting from {{code|Fruit}}. Now, in the {{code|eat}} method we can write <syntaxhighlight lang="objc"> - (void)eat:(id)sth { if ([sth isKindOfClass:[Fruit class]]) { // we're actually eating a Fruit, so continue if ([sth isMemberOfClass:[Apple class]]) { eatApple(sth); } else if ([sth isMemberOfClass:[Orange class]]) { eatOrange(sth); } else { error(); } } else { error(); } } </syntaxhighlight> Now, when {{code|eat}} is called with a generic object (an {{code|id}}), the function will behave correctly depending on the type of the generic object. ===C++=== C++ supports type introspection via the [[run-time type information]] (RTTI) [[typeid]] and [[dynamic cast]] keywords. The {{code|dynamic_cast}} expression can be used to determine whether a particular object is of a particular derived class. For instance: <syntaxhighlight lang="cpp"> Person* p = dynamic_cast<Person *>(obj); if (p != nullptr) { p->walk(); } </syntaxhighlight> The {{code|typeid}} operator retrieves a {{code|std::type_info}} object describing the most derived type of an object: <syntaxhighlight lang="cpp"> if (typeid(Person) == typeid(*obj)) { serialize_person( obj ); } </syntaxhighlight> ===Object Pascal=== Type introspection has been a part of Object Pascal since the original release of Delphi, which uses RTTI heavily for visual form design. In Object Pascal, all classes descend from the base TObject class, which implements basic RTTI functionality. Every class's name can be referenced in code for RTTI purposes; the class name identifier is implemented as a pointer to the class's metadata, which can be declared and used as a variable of type TClass. The language includes an '''is''' operator, to determine if an object is or descends from a given class, an '''as''' operator, providing a type-checked typecast, and several TObject methods. Deeper introspection (enumerating fields and methods) is traditionally only supported for objects declared in the $M+ (a pragma) state, typically TPersistent, and only for symbols defined in the published section. Delphi 2010 increased this to nearly all symbols. <syntaxhighlight lang="delphi"> procedure Form1.MyButtonOnClick(Sender: TObject); var aButton: TButton; SenderClass: TClass; begin SenderClass := Sender.ClassType; //returns Sender's class pointer if sender is TButton then begin aButton := sender as TButton; EditBox.Text := aButton.Caption; //Property that the button has but generic objects don't end else begin EditBox.Text := Sender.ClassName; //returns the name of Sender's class as a string end; end; </syntaxhighlight> ===Java=== The simplest example of type introspection in Java is the {{code|instanceof}}<ref>[http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.20.2 Java Language Specification: instanceof]</ref> operator. The {{code|instanceof}} operator determines whether a particular object belongs to a particular class (or a subclass of that class, or a class that implements that interface). For instance: <syntaxhighlight lang="java"> if (obj instanceof Person p) { p.walk(); } </syntaxhighlight> The {{code|java.lang.Class}}<ref>[http://java.sun.com/javase/6/docs/api/java/lang/Class.html Java API: java.lang.Class]</ref> class is the basis of more advanced introspection. For instance, if it is desirable to determine the actual class of an object (rather than whether it is a member of a ''particular'' class), {{code|Object.getClass()}} and {{code|Class.getName()}} can be used: <syntaxhighlight lang="java"> System.out.println(obj.getClass().getName()); </syntaxhighlight> ===PHP=== In [[PHP]] introspection can be done using {{code|instanceof}} operator. For instance: <syntaxhighlight lang="php"> if ($obj instanceof Person) { // Do whatever you want } </syntaxhighlight> ===Perl=== Introspection can be achieved using the {{code|ref}} and {{code|isa}} functions in [[Perl]]. We can introspect the following classes and their corresponding instances: <syntaxhighlight lang="perl"> package Animal; sub new { my $class = shift; return bless {}, $class; } package Dog; use base 'Animal'; package main; my $animal = Animal->new(); my $dog = Dog->new(); </syntaxhighlight> using: <syntaxhighlight lang="perl"> print "This is an Animal.\n" if ref $animal eq 'Animal'; print "Dog is an Animal.\n" if $dog->isa('Animal'); </syntaxhighlight> ====Meta-Object Protocol==== Much more powerful introspection in Perl can be achieved using the [[Moose (Perl)|Moose]] object system<ref>[https://metacpan.org/module/Moose::Manual::MOP Moose meta API documentation]</ref> and the {{code|Class::MOP}} [[meta-object]] protocol;<ref>[https://metacpan.org/module/Class::MOP Class::MOP - a meta-object protocol for Perl]</ref> for example, you can check if a given object ''does'' a [[Role (computer science)|role]] {{var|X}}: <syntaxhighlight lang="perl"> if ($object->meta->does_role("X")) { # do something ... } </syntaxhighlight> This is how you can list fully qualified names of all of the methods that can be invoked on the object, together with the classes in which they were defined: <syntaxhighlight lang="perl"> for my $method ($object->meta->get_all_methods) { print $method->fully_qualified_name, "\n"; } </syntaxhighlight> ===Python=== The most common method of introspection in [[Python (programming language)|Python]] is using the {{code|dir}} function to detail the attributes of an object. For example: <syntaxhighlight lang="python"> class Foo: def __init__(self, val): self.x = val def bar(self): return self.x </syntaxhighlight> <syntaxhighlight lang="pycon"> >>> dir(Foo(5)) ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'bar', 'x'] </syntaxhighlight> Also, the built-in functions {{code|type}} and {{code|isinstance}} can be used to determine what an object ''is'' while {{code|hasattr}} can determine what an object ''does''. For example: <syntaxhighlight lang="pycon"> >>> a = Foo(10) >>> b = Bar(11) >>> type(a) <type 'Foo'> >>> isinstance(a, Foo) True >>> isinstance(a, type(a)) True >>> isinstance(a, type(b)) False >>> hasattr(a, 'bar') True </syntaxhighlight> ===Ruby=== Type introspection is a core feature of [[Ruby (programming language)|Ruby]]. In Ruby, the Object class (ancestor of every class) provides {{code|Object#instance_of?}} and {{code|Object#kind_of?}} methods for checking the instance's class. The latter returns true when the particular instance the message was sent to is an instance of a descendant of the class in question. For example, consider the following example code (you can immediately try this with the [[Interactive Ruby Shell]]): <syntaxhighlight lang="irb"> $ irb irb(main):001:0> A=Class.new => A irb(main):002:0> B=Class.new A => B irb(main):003:0> a=A.new => #<A:0x2e44b78> irb(main):004:0> b=B.new => #<B:0x2e431b0> irb(main):005:0> a.instance_of? A => true irb(main):006:0> b.instance_of? A => false irb(main):007:0> b.kind_of? A => true </syntaxhighlight> In the example above, the {{code|Class}} class is used as any other class in Ruby. Two classes are created, {{code|A}} and {{code|B}}, the former is being a superclass of the latter, then one instance of each class is checked. The last expression gives true because {{code|A}} is a superclass of the class of {{code|b}}. Further, you can directly ask for the class of any object, and "compare" them (code below assumes having executed the code above): <syntaxhighlight lang="irb"> irb(main):008:0> A.instance_of? Class => true irb(main):009:0> a.class => A irb(main):010:0> a.class.class => Class irb(main):011:0> A > B => true irb(main):012:0> B <= A => true </syntaxhighlight> ===ActionScript === In [[ActionScript]] (as3), the function <code>[https://web.archive.org/web/20090220055607/http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/utils/package.html#getQualifiedClassName() flash.utils.getQualifiedClassName]</code> can be used to retrieve the class/type name of an arbitrary object. <syntaxhighlight lang="actionscript"> // all classes used in as3 must be imported explicitly import flash.utils.getQualifiedClassName; import flash.display.Sprite; // trace is like System.out.println in Java or echo in PHP trace(flash.utils.getQualifiedClassName("I'm a String")); // "String" trace(flash.utils.getQualifiedClassName(1)); // "int", see dynamic casting for why not Number trace(flash.utils.getQualifiedClassName(new flash.display.Sprite())); // "flash.display.Sprite" </syntaxhighlight> Alternatively, the operator <code>[https://web.archive.org/web/20090217193939/http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/operators.html#is is]</code> can be used to determine if an object is of a specific type: <syntaxhighlight lang="actionscript"> // trace is like System.out.println in Java or echo in PHP trace("I'm a String" is String); // true trace(1 is String); // false trace("I'm a String" is Number); // false trace(1 is Number); // true </syntaxhighlight> This second function can be used to test [[Inheritance (object-oriented programming)|class inheritance]] parents as well: <syntaxhighlight lang="actionscript"> import flash.display.DisplayObject; import flash.display.Sprite; // extends DisplayObject trace(new flash.display.Sprite() is flash.display.Sprite); // true trace(new flash.display.Sprite() is flash.display.DisplayObject); // true, because Sprite extends DisplayObject trace(new flash.display.Sprite() is String); // false </syntaxhighlight> ====Meta-type introspection==== Like Perl, ActionScript can go further than getting the class name, but all the metadata, functions and other elements that make up an object using the <code>[https://web.archive.org/web/20090220055607/http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/utils/package.html#describeType() flash.utils.describeType]</code> function; this is used when implementing [[Reflection (computer science)|reflection]] in ActionScript. <syntaxhighlight lang="actionscript"> import flash.utils.describeType; import flash.utils.getDefinitionByName; import flash.utils.getQualifiedClassName; import flash.display.Sprite; var className:String = getQualifiedClassName(new flash.display.Sprite()); // "flash.display.Sprite" var classRef:Class = getDefinitionByName(className); // Class reference to flash.display{{Not a typo|.}}Sprite // eg. 'new classRef()' same as 'new flash.display.Sprite()' trace(describeType(classRef)); // return XML object describing type // same as : trace(describeType(flash.display.Sprite)); </syntaxhighlight> == See also == * [[Reification (computer science)]] * [[typeof]] == References == {{Reflist}} ==External links== *[http://rosettacode.org/wiki/Introspection Introspection] on [http://rosettacode.org/ Rosetta Code] {{DEFAULTSORT:Type Introspection}} [[Category:Object-oriented programming]] [[Category:Programming language comparisons]] <!-- Hidden categories below --> [[Category:Articles with example C++ code]] [[Category:Articles with example Java code]] [[Category:Articles with example Objective-C code]] [[Category:Articles with example Pascal code]] [[Category:Articles with example Perl code]] [[Category:Articles with example PHP code]] [[Category:Articles with example Python (programming language) code]] [[Category:Articles with example Ruby code]] [[fr:Introspection (informatique)]]
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)
Pages transcluded onto the current version of this page
(
help
)
:
Template:Code
(
edit
)
Template:Multiple issues
(
edit
)
Template:Not a typo
(
edit
)
Template:Reflist
(
edit
)
Template:Var
(
edit
)