Type introspection
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). ExamplesObjective-CIn Objective-C, for example, both the generic Object and NSObject (in Cocoa/OpenStep) provide the method For example, say we have an Now, in the - (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();
}
}
Now, when C++C++ supports type introspection via the run-time type information (RTTI) typeid and dynamic cast keywords.
The Person* p = dynamic_cast<Person *>(obj);
if (p != nullptr) {
p->walk();
}
The if (typeid(Person) == typeid(*obj)) {
serialize_person( obj );
}
Object PascalType 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. 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;
JavaThe simplest example of type introspection in Java is the if (obj instanceof Person p) {
p.walk();
}
The 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), System.out.println(obj.getClass().getName());
PHPIn PHP introspection can be done using if ($obj instanceof Person) {
// Do whatever you want
}
PerlIntrospection can be achieved using the We can introspect the following classes and their corresponding instances: 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();
using: print "This is an Animal.\n" if ref $animal eq 'Animal';
print "Dog is an Animal.\n" if $dog->isa('Animal');
Meta-Object ProtocolMuch more powerful introspection in Perl can be achieved using the Moose object system[3] and the if ($object->meta->does_role("X")) {
# do something ...
}
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: for my $method ($object->meta->get_all_methods) {
print $method->fully_qualified_name, "\n";
}
PythonThe most common method of introspection in Python is using the class Foo:
def __init__(self, val):
self.x = val
def bar(self):
return self.x
>>> dir(Foo(5))
['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
'__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__str__', '__weakref__', 'bar', 'x']
Also, the built-in functions >>> 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
RubyType introspection is a core feature of Ruby. In Ruby, the Object class (ancestor of every class) provides $ 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
In the example above, the Further, you can directly ask for the class of any object, and "compare" them (code below assumes having executed the code above): 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
ActionScriptIn ActionScript (as3), the function // 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"
Alternatively, the operator // 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
This second function can be used to test class inheritance parents as well: 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
Meta-type introspectionLike 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 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));
See alsoReferencesExternal links |
Portal di Ensiklopedia Dunia