Type introspection

From Vero - Wikipedia
Revision as of 21:07, 6 October 2025 by 2806:2f0:9d41:f328:c394:6fb6:bb4a:f796 (talk) (android.enableR8.fullMode=false # Remove this line from your codebase.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Template:Short description Template:Multiple issues 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.

Introspection should not be confused with 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, Python, Julia, and Go).

Examples

C++

C++ supports type introspection via the run-time type information (RTTI) typeid and dynamic cast keywords. The Template:Code 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) {

   p->walk();

} </syntaxhighlight> The Template:Code operator retrieves a Template:Code object describing the most derived type of an object: <syntaxhighlight lang="cpp"> if (typeid(Person) == typeid(*obj)) {

   serializePerson(obj);

} </syntaxhighlight>

C#

In C# introspection can be done using the Template:Code keyword. For instance: <syntaxhighlight lang="csharp"> if (obj is Person) {

   // Do whatever you want

} </syntaxhighlight>

Objective-C

In Objective-C, for example, both the generic Object and NSObject (in Cocoa/OpenStep) provide the method Template:Code which returns true if the argument to the method is an instance of the specified class. The method Template:Code analogously returns true if the argument inherits from the specified class.

For example, say we have an Template:Code and an Template:Code class inheriting from Template:Code.

Now, in the Template:Code 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 Template:Code is called with a generic object (an Template:Code), the function will behave correctly depending on the type of the generic object.

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 Template:Code<ref>Java Language Specification: instanceof</ref> operator. The Template:Code 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 Template:Code<ref>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), Template:Code and Template:Code can be used:

<syntaxhighlight lang="java"> System.out.println(obj.getClass().getName()); </syntaxhighlight>

PHP

In PHP introspection can be done using Template:Code operator. For instance: <syntaxhighlight lang="php"> if ($obj instanceof Person) {

   // Do whatever you want

} </syntaxhighlight>

Perl

Introspection can be achieved using the Template:Code and Template:Code 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 object system<ref>Moose meta API documentation</ref> and the Template:Code meta-object protocol;<ref>Class::MOP - a meta-object protocol for Perl</ref> for example, you can check if a given object does a role Template:Var: <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 is using the Template:Code function to detail the attributes of an object. For example: <syntaxhighlight lang="python"> class Foo:

   def __init__(self, val: int) -> None:
       self.x = val
   def get_x(self) -> int:
       return self.x

</syntaxhighlight>

<syntaxhighlight lang="python"> print(dir(Foo(5)))

  1. prints ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'bar', 'x']

</syntaxhighlight>

Also, the built-in functions Template:Code and Template:Code can be used to determine what an object is while Template:Code can determine what an object does. For example:

<syntaxhighlight lang="python"> a: Foo = Foo(10) b: Bar = Bar(11) print(type(a))

  1. prints <type 'Foo'>

isinstance(a, Foo)

  1. prints True

print(isinstance(a, type(a)))

  1. prints True

print(isinstance(a, type(b)))

  1. prints False

print(hasattr(a, 'bar'))

  1. prints True

</syntaxhighlight>

Ruby

Type introspection is a core feature of Ruby. In Ruby, the Object class (ancestor of every class) provides Template:Code and Template:Code 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 Template:Code class is used as any other class in Ruby. Two classes are created, Template:Code and Template:Code, the former is being a superclass of the latter, then one instance of each class is checked. The last expression gives true because Template:Code is a superclass of the class of Template:Code.

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 flash.utils.getQualifiedClassName 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(getQualifiedClassName("I'm a String")); // "String" trace(getQualifiedClassName(1)); // "int", see dynamic casting for why not Number trace(getQualifiedClassName(new Sprite())); // "flash.display.Sprite" </syntaxhighlight>

Alternatively, the operator is 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 class inheritance parents as well: <syntaxhighlight lang="actionscript"> import flash.display.DisplayObject; import flash.display.Sprite; // extends DisplayObject

trace(new Sprite() is Sprite); // true trace(new Sprite() is DisplayObject); // true, because Sprite extends DisplayObject trace(new 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 flash.utils.describeType function; this is used when implementing 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 Sprite()); // "flash.display.Sprite" var classRef: Class = getDefinitionByName(className); // Class reference to flash.displayTemplate:Not a typoSprite // 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

References

Template:Reflist

[[fr:Introspection (informatique)]