stringtranslate.com

Tipo de introspección

En informática , la introspección de tipos es la capacidad de un programa de examinar el tipo o las propiedades de un objeto en tiempo de ejecución . Algunos lenguajes de programación poseen esta capacidad.

No se debe confundir la introspección con la reflexión , que va un paso más allá y es la capacidad que tiene un programa de manipular los valores, metadatos, propiedades y funciones de un objeto en tiempo de ejecución. Algunos lenguajes de programación también poseen esa capacidad (por ejemplo, Java , Python , Julia y Go ).

Ejemplos

C objetivo

En Objective-C , por ejemplo, tanto el objeto genérico como NSObject (en Cocoa / OpenStep ) proporcionan el método isMemberOfClass: que devuelve verdadero si el argumento del método es una instancia de la clase especificada. De manera análoga, el método isKindOfClass:devuelve verdadero si el argumento hereda de la clase especificada.

Por ejemplo, digamos que tenemos una clase Appley Orangeque hereda de Fruit.

Ahora, en el eatmétodo podemos escribir

-  ( void ) comer: ( id ) algo { if ([ sth isKindOfClass : [ Fruit class ]]) { // en realidad estamos comiendo una fruta, así que continúa if ([ sth isMemberOfClass : [ Apple class ]]) { eatApple ( algo ); } else if ([ algo esMemberOfClass : [ Clase naranja ]]) { comerOrange ( algo ); } más { error (); } } más { error (); } }                               

Ahora, cuando eatse llama con un objeto genérico (an id), la función se comportará correctamente dependiendo del tipo de objeto genérico.

C++

C++ admite la introspección de tipos a través de las palabras clave typeid ydynamic_cast de información de tipo en tiempo de ejecución (RTTI) . La expresión se puede utilizar para determinar si un objeto particular pertenece a una clase derivada particular. Por ejemplo:dynamic_cast

Persona * p = dynamic_cast < Persona *> ( obj ); si ( p != nullptr ) { p -> caminar (); }         

El typeidoperador recupera un std::type_infoobjeto que describe el tipo más derivado de un objeto:

if ( typeid ( Persona ) == typeid ( * obj )) { serialize_person ( obj ); }       

Objeto Pascal

La introspección de tipos ha sido parte de Object Pascal desde el lanzamiento original de Delphi, que utiliza RTTI en gran medida para el diseño de formularios visuales. En Object Pascal, todas las clases descienden de la clase base TObject, que implementa la funcionalidad RTTI básica. Se puede hacer referencia al nombre de cada clase en el código para fines RTTI; el identificador del nombre de la clase se implementa como un puntero a los metadatos de la clase, que se puede declarar y utilizar como una variable de tipo TClass. El lenguaje incluye un operador is , para determinar si un objeto es o desciende de una clase determinada, un operador as , que proporciona un encasillado con verificación de tipo, y varios métodos TObject. Tradicionalmente, la introspección más profunda (enumeración de campos y métodos) solo se admite para objetos declarados en el estado $M+ (un pragma), generalmente TPersistent, y solo para símbolos definidos en la sección publicada. Delphi 2010 aumentó esto a casi todos los símbolos.

procedimiento Formulario1 . MyButtonOnClick ( Remitente : TObject ) ; var aButton : TButton ; Clase de remitente : Clase T ; comenzar SenderClass : = Remitente . Tipo de clase ; //devuelve el puntero de clase del remitente si el remitente es TButton y luego comienza aButton := remitente como TButton ; Cuadro de edición . Texto := unBotón . Subtítulo ; //Propiedad que tiene el botón pero los objetos genéricos no terminan sino comienzan EditBox . Texto := Remitente . Nombre de la clase ; //devuelve el nombre de la clase del remitente como final de cadena ; fin ;                                 

Java

El ejemplo más simple de introspección de tipos en Java es el operador instanceof[1] . El instanceofoperador determina si un objeto particular pertenece a una clase particular (o una subclase de esa clase, o una clase que implementa esa interfaz). Por ejemplo:

if ( obj instanciade Persona ) { Persona p = ( Persona ) obj ; pag . caminar (); }         

La clase java.lang.Class[2] es la base de una introspección más avanzada.

Por ejemplo, si es deseable determinar la clase real de un objeto (en lugar de si es miembro de una clase particular ), Object.getClass()se Class.getName()puede utilizar:

Sistema . afuera . println ( obj . getClass (). getName ());

PHP

En PHP, la introspección se puede realizar utilizando instanceofel operador. Por ejemplo:

if  ( $obj  instanciade  Persona )  {  // Haz lo que quieras }

perla

La introspección se puede lograr utilizando las funciones refy isaen Perl .

Podemos hacer una introspección de las siguientes clases y sus instancias correspondientes:

paquete de animales ; sub nuevo { mi $clase = turno ; volver bendice {}, $clase ; }           paquete Perro ; utilizar la base 'Animal' ;   paquete principal ; mi $animal = Animal -> nuevo (); mi $perro = Perro -> nuevo ();       

usando:

print "Este es un animal.\n" if ref $animal eq 'Animal' ; print "El perro es un animal.\n" if $perro -> isa ( 'Animal' );         

Protocolo de metaobjeto

Se puede lograr una introspección mucho más poderosa en Perl utilizando el sistema de objetos Moose [3] y el protocolo Class::MOP de metaobjetos ; [4] por ejemplo, puedes comprobar si un objeto determinado cumple una función X :

if ( $objeto -> meta -> Does_role ( "X" )) { # hacer algo... }   

Así es como puede enumerar los nombres completos de todos los métodos que se pueden invocar en el objeto, junto con las clases en las que se definieron:

para mi $método ( $objeto -> meta -> get_all_methods ) { print $método -> nombre_completamente_calificado , "\n" ; }       

Pitón

El método de introspección más común en Python es utilizar la dirfunción para detallar los atributos de un objeto. Por ejemplo:

clase  Foo :  def  __init__ ( self ,  val ):  self . x  =  valor def  bar ( self ):  devolver  self . X
>>> dir ( Foo ( 5 )) ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__' , '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'bar', 'x']

Además, las funciones integradas typey isinstancese pueden utilizar para determinar qué es un objeto, mientras que pueden determinar qué hacehasattr un objeto . Por ejemplo:

>>> a  =  Foo ( 10 ) >>> b  =  Bar ( 11 ) >>> tipo ( a ) <tipo 'Foo'> >>> isinstance ( a ,  Foo ) Verdadero >>> isinstance ( a ,  tipo ( a )) Verdadero >>> isinstance ( a ,  tipo ( b )) Falso >>> hasattr ( a ,  'barra' ) Verdadero

Rubí

La introspección de tipos es una característica central de Ruby . En Ruby, la clase Objeto (antepasada de cada clase) proporciona Object#instance_of?métodos Object#kind_of?para verificar la clase de la instancia. Este último devuelve verdadero cuando la instancia particular a la que se envió el mensaje es una instancia de un descendiente de la clase en cuestión. Por ejemplo, considere el siguiente código de ejemplo (puede probarlo inmediatamente con Interactive Ruby Shell ):

$ irb irb(principal):001:0> A = Clase . nuevo => A irb(principal):002:0> B = Clase . nuevo A => B irb(principal):003:0> a = A . nuevo => #<A:0x2e44b78> irb(principal):004:0> b = B . nuevo => #<B:0x2e431b0> irb(principal):005:0> a . ¿en vez de? A => verdadero irb(principal):006:0> b . ¿en vez de? A => falso irb(principal):007:0> b . ¿un poco? A => verdadero    

En el ejemplo anterior, la Classclase se utiliza como cualquier otra clase en Ruby. Se crean dos clases Ay B, la primera es una superclase de la segunda, luego se verifica una instancia de cada clase. La última expresión da verdadera porque Aes una superclase de la clase de b.

Además, puede solicitar directamente la clase de cualquier objeto y "compararlos" (el código siguiente supone haber ejecutado el código anterior):

irb(principal):008:0> A . ¿en vez de? Clase => verdadero irb(principal):009:0> a . clase => A irb(principal):010:0> a . clase . clase => Clase irb(principal):011:0> A > B => verdadero irb(principal):012:0> B <= A => verdadero     

script de acción

En ActionScript (as3), la función flash.utils.getQualifiedClassNamese puede utilizar para recuperar el nombre de clase/tipo de un objeto arbitrario.

// todas las clases utilizadas en as3 deben importarse explícitamente import flash . utiles . getNombreClaseCalificada ; importar flash . mostrar . duende ; // trace es como System.out.println en Java o echo en PHP trace ( flash . utils . getQualifiedClassName ( "Soy una cadena" )); // Seguimiento de "cadena" ( flash . utils . getQualifiedClassName ( 1 )); // "int", consulte la conversión dinámica para saber por qué no el seguimiento numérico ( flash . utils . getQualifiedClassName ( new flash . display . Sprite ())); // "flash.display.Sprite"      

Alternativamente, el operador isse puede utilizar para determinar si un objeto es de un tipo específico:

// trace es como System.out.println en Java o echo en PHP trace ( "Soy una cadena" es String ); // rastro verdadero ( 1 es Cadena ); // rastro falso ( "Soy una cadena" es Número ); // seguimiento falso ( 1 es Número ); // verdadero            

Esta segunda función también se puede utilizar para probar los padres de herencia de clases :

importar flash . mostrar . Objeto de visualización ; importar flash . mostrar . duende ; // extiende DisplayObject   trace ( nuevo flash . display . Sprite () es flash . display . Sprite ); // rastro verdadero ( new flash . display . Sprite () es flash . display . DisplayObject ); // verdadero, porque Sprite extiende el seguimiento de DisplayObject ( new flash . display . Sprite () es String ); // FALSO            

Introspección de metatipo

Al igual que Perl, ActionScript puede ir más allá de obtener el nombre de la clase, sino todos los metadatos, funciones y otros elementos que componen un objeto que utiliza la flash.utils.describeTypefunción; esto se utiliza al implementar la reflexión en ActionScript.

importar flash . utiles . describirTipo ; importar flash . utiles . getDefiniciónPorNombre ; importar flash . utiles . getNombreClaseCalificada ; importar flash . mostrar . duende ;    var className : String = getQualifiedClassName ( nuevo flash . display . Sprite ()); // "flash.display.Sprite" var classRef : Clase = getDefinitionByName ( className ); // Referencia de clase a flash.display{{No es un error tipográfico|.}}Sprite // por ejemplo. 'new classRef()' igual que el rastreo 'new flash.display.Sprite()' ( describeType ( classRef )); // devuelve un objeto XML que describe el tipo // igual que: trace(describeType(flash.display.Sprite));          

Ver también

Referencias

  1. ^ Especificación del lenguaje Java: instancia de
  2. ^ API de Java: java.lang.Class
  3. ^ Documentación de la meta API de Moose
  4. ^ Clase::MOP: un protocolo de metaobjeto para Perl

enlaces externos