- Introspección de tipos
-
En informática, la introspección de tipos es la capacidad de algunos lenguaje de programación orientado a objetos de determinar el tipo de un objeto en tiempo de ejecución. Esta es una característica notable de Objective-C, y una característica común en todo lenguaje que permita que clases de objetos sean manipuladas como objetos de clase primera por el programador. La introspección de tipos puede ser utilizada para implementar polimorfismo.
Contenido
Ejemplos
Ruby
La introspección de tipos es una característica básica de Ruby. En Ruby, la clase Object (padre de toda clase) incluye los métodos Object#instance_of? y Object#kind_of? para comprobar la clase de cualquier instancia. La última devuelve true cuando la instancia particular a la que se le envió el mensaje era una instancia de un descendiente de esta clase en cuestión. Para clarificar, considérese seguir el siguiente código de ejemplo (que puede probarse inmediatamente con 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.send '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
En el ejemplo anterior, la clase Class se usa como cualquier otra clase en Ruby. Se crean dos clases, A y B, siendo la primera padre de la segunda, y luego se comprueba una instancia de cada clase. La última expresión nos devuelve verdadero porque A es una superclase de la clase de b. En el ejemplo inferior se muestra un método alternativo en Ruby que puede utilizarse para definir clases (y que lleva a un resultado idéntico):
$ irb irb(main):001:0> class A; end => nil irb(main):002:0> class B < A; end => nil irb(main):003:0> a=A.new => #<A:0x2e4c33c> irb(main):004:0> b=B.new => #<B:0x2e4a974> 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
También se puede preguntar directamente por la clase de cualquier objeto, y "compararlos" (el siguiente código asume haber ejecutado el código superior):
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
Objective-C
En Objective-C, por ejemplo, ambos objetos genéricos Object y NSObject (en Cocoa/OpenStep) proporcionan el método isMemberOfClass: que devuelve true si el argumento al método es una instancia de la clase especificada. El método isKindOfClass: devuelve true si el argumento, de forma análoga, es descendiente de la clase especificada.
Por ejemplo, digamos que tenemos un par de clases Perrito y Gatito descendientes de una clase Animal, y una clase Veterinario.
Ahora, en el método desex puede escribirse
- desex: (id) to_desex { if([to_desex isKindOfClass:[Animal class]]) { //we're actually desexing an Animal, so continue if([to_desex isMemberOfClass:[Perrito class]]) desex_dog(to_desex); else if([to_desex isMemberOfClass:[Gatito class]]) desex_cat(to_desex); else error(); } else { error(); } }
Ahora, cuando se llama a desex con un objeto genérico (un id), la función se comportará de forma correcta dependiendo del tipo de objeto genérico.
C++
C++ soporta introspección de tipos a través de las palabras clave typeid y dynamic cast.
La expresión
dynamic_cast
puede utilizarse para determinar si un objeto en concreto es de una clase determinada. Por ejemplo:if(Persona *p = dynamic_cast<Persona *>(obj)){ p->andar(); }
El operador
typeid
devuelve un objetostd::type_info
que describe el tipo más derivado de un objeto:std::cout << typeid(obj).name() << std::endl;
Object Pascal
La introspección de tipos ha sido parte de Object Pascal desde la primera versión de Delphi, que usa mucho RTTI para diseño visual de formularios. En Object Pascal, toda clase desciende de la clase base TObject, que implementa funcionalidad RTTI básica. El nombre de cada clase puede refrenciarse en código para propósitos de RTTI; el identificador del nombre de clase está implementado como un puntero a los metadatos de la clase, que pueden ser declarados y usados como una variable de tipo TClass.
El lenguaje include un operador is, para determinar si un objeto es o desciende de una clase determinada, así como un operador as, que proporciona typecast con comprobación de tipos, y varios métodos en TObject.
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;
Introspección de Objetos Java
El ejemplo más sencillo de introspección de tipos en Java es el operador
instanceof
. El operadorinstanceof
determina si un objeto concreto pertenece a una clase en particular (o a una subclase de esta, o a una clase que implemente tal interfaz). Por ejemplo:if(obj instanceof Persona){ Persona p = (Persona)obj; p.andar(); }
La clase
java.lang.Class
[1] es la base de una introspeción más avanzada.Como ejemplo, si se desea determinar la clase actual de un objeto (más que si un objeto pertenece a una clase en concreto), pueden utilizarse los métodos
Object.getClass()
yClass.getName()
:System.out.println(obj.getClass().getName());
Perl
Se puede lograr introspección con las funciones
ref
eisa
Perl.Podemos realizar introspección sobre las clases siguientes y sus instancias correspondientes:
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();
utilizando:
print "This is an Animal.\n" if ref $animal eq 'Animal'; print "Dog is an Animal.\n" if $dog->isa('Animal');
Meta-Object Protocol (MOP)
Se puede lograr una introspección mucho mayor en Perl utilizando el sistema de objetos Moose[2] y la
Class::MOP
protocolo meta-object,[3] por ejemplo de esta forma se puede comprobar si un objeto determinado realiza un rolX
:if ($object->meta->does_role("X")) { # do something ... }
Se puede listar como sigue una lista de los nombres completamente cualificados de todos los métodos que pueden ser invocados en el objeto, junto con las clases en donde fueron definidos::
for my $method ($object->meta->get_all_methods) { print $method->fully_qualified_name, "\n"; }
Véase también
Referencias
- ↑ Java API: java.lang.Class
- ↑ Moose meta API documentation (en inglés)
- ↑ Class::MOP - a meta-object protocol for Perl (en inglés)
Enlaces externos
- Introspección en Rosetta Code (en inglés)
Categorías:- Programación orientada a objetos
- Artículos con código C++ de ejemplo
Wikimedia foundation. 2010.