Digite introspecção - Type introspection

Na computação , a introspecção de tipo é a capacidade de um programa de examinar o tipo ou as propriedades de um objeto em tempo de execução . Algumas linguagens de programação possuem esse recurso.

A introspecção não deve ser confundida com reflexão , que vai um passo além e é a capacidade de um programa de manipular os valores, metadados, propriedades e funções de um objeto em tempo de execução. Algumas linguagens de programação também possuem esse recurso (por exemplo, Java , Python , Julia e Go ).

Exemplos

Rubi

A introspecção de tipo é uma característica central do Ruby . Em Ruby, a classe Object (ancestral de cada classe) fornece Object#instance_of?e Object#kind_of?métodos para verificar a classe da instância. O último retorna verdadeiro quando a instância específica para a qual a mensagem foi enviada é uma instância de um descendente da classe em questão. Por exemplo, considere o seguinte código de exemplo (você pode tentar isso imediatamente com o Shell Ruby Interativo ):

$ 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

No exemplo acima, a Classclasse é usada como qualquer outra classe em Ruby. Duas classes são criadas Ae B, a primeira é uma superclasse da última, então uma instância de cada classe é verificada. A última expressão é verdadeira porque Aé uma superclasse da classe de b.

Além disso, você pode solicitar diretamente a classe de qualquer objeto e "compará-los" (o código abaixo pressupõe a execução do código acima):

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

Em Objective-C , por exemplo, ambos Object genérico e NSObject (em Cocoa / OpenStep ) fornecem o método isMemberOfClass: que retorna true se o argumento para o método for uma instância da classe especificada. O método isKindOfClass:retorna true analogamente se o argumento for herdado da classe especificada.

Por exemplo, digamos que temos um Applee uma Orangeclasse herdando de Fruit.

Agora, no eatmétodo, podemos escrever

- (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();
    }
}

Agora, quando eaté chamada com um objeto genérico (an id), a função se comportará corretamente dependendo do tipo do objeto genérico.

C ++

C ++ oferece suporte à introspecção de tipo por meio das palavras-chave typeid e dynamic_cast de informações de tipo de tempo de execução (RTTI) . A expressão pode ser usada para determinar se um determinado objeto pertence a uma determinada classe derivada. Por exemplo: dynamic_cast

Person* p = dynamic_cast<Person *>(obj);
if (p != nullptr) {
  p->walk();
}

O typeidoperador recupera um std::type_infoobjeto que descreve o tipo mais derivado de um objeto:

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

Object Pascal

A introspecção de tipos faz parte do Object Pascal desde o lançamento original do Delphi, que usa RTTI intensamente para design de formas visuais. Em Object Pascal, todas as classes descendem da classe base TObject, que implementa a funcionalidade RTTI básica. O nome de cada classe pode ser referenciado no código para fins de RTTI; o identificador do nome da classe é implementado como um ponteiro para os metadados da classe, que podem ser declarados e usados ​​como uma variável do tipo TClass. A linguagem inclui uma é operador, para determinar se um objecto é ou desce a partir de uma dada classe, um como operador, proporcionando um estereotipado verificado-tipo, e vários métodos TObject. Uma introspecção mais profunda (enumerando campos e métodos) é tradicionalmente suportada apenas para objetos declarados no estado $ M + (um pragma), normalmente TPersistent, e apenas para símbolos definidos na seção publicada. O Delphi 2010 aumentou isso para quase todos os símbolos.

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;

Java

O exemplo mais simples de introspecção de tipo em Java é o instanceofoperador. O instanceofoperador determina se um determinado objeto pertence a uma determinada classe (ou a uma subclasse dessa classe, ou a uma classe que implementa essa interface). Por exemplo:

if (obj instanceof Person) {
    Person p = (Person)obj;
    p.walk();
}

A java.lang.Classaula é a base de uma introspecção mais avançada.

Por exemplo, se for desejável determinar a classe real de um objeto (em vez de se é um membro de uma classe particular ), Object.getClass()e Class.getName()pode ser usado:

System.out.println(obj.getClass().getName());

PHP

No PHP, a introspecção pode ser feita usando o instanceofoperador. Por exemplo:

if ($obj instanceof Person) {
    // Do whatever you want
}

Perl

A introspecção pode ser alcançada usando as funções refe isaem Perl .

Podemos introspectar as seguintes classes e suas instâncias correspondentes:

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();

usando:

print "This is an Animal.\n" if ref $animal eq 'Animal';
print "Dog is an Animal.\n" if $dog->isa('Animal');

Protocolo de Meta-Objeto

Uma introspecção muito mais poderosa em Perl pode ser alcançada usando o sistema de objetos Moose e o protocolo de Class::MOP meta-objetos ; por exemplo, você pode verificar se um determinado objeto faz um papel X :

if ($object->meta->does_role("X")) {
    # do something ...
}

É assim que você pode listar nomes totalmente qualificados de todos os métodos que podem ser chamados no objeto, junto com as classes nas quais foram definidos:

for my $method ($object->meta->get_all_methods) {
    print $method->fully_qualified_name, "\n";
}

Pitão

O método mais comum de introspecção em Python é usar a dirfunção para detalhar os atributos de um objeto. Por exemplo:

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']

Além disso, o built-in funções typee isinstancepode ser usado para determinar o que um objeto é ao mesmo tempo hasattrpode determinar o que um objeto faz . Por exemplo:

>>> 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

ActionScript (as3)

No ActionScript , a função flash.utils.getQualifiedClassNamepode ser usada para recuperar o nome da classe / tipo de um objeto arbitrário.

// 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"

Como alternativa, o operador ispode ser usado para determinar se um objeto é de um tipo específico:

// 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

Esta segunda função também pode ser usada para testar pais de herança de classe :

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

Introspecção de metatipo

Como Perl, o ActionScript pode ir além de obter o nome da classe, mas todos os metadados, funções e outros elementos que compõem um objeto usando a flash.utils.describeTypefunção; isso é usado ao implementar reflexão no 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));

Veja também

Referências

links externos