Типа самоанализ

редактировать

В вычислениях, тип интроспекция является способность программы для изучения на типе или свойства объекта на время выполнения. Некоторые языки программирования обладают такой возможностью.

Самоанализ не следует путать с отражением, которое идет дальше и представляет собой способность программы манипулировать значениями, метаданными, свойствами и функциями объекта во время выполнения. Некоторые языки программирования также обладают такой возможностью (например, Java, Python, Julia и Go ).

СОДЕРЖАНИЕ

  • 1 Примеры
    • 1.1 Рубин
    • 1.2 Цель-C
    • 1.3 C ++
    • 1.4 Object Pascal
    • 1.5 Java
    • 1.6 PHP
    • 1.7 Perl
      • 1.7.1 Протокол метаобъектов
    • 1.8 Python
    • 1.9 ActionScript (as3)
      • 1.9.1 Самоанализ мета-типа
  • 2 См. Также
  • 3 ссылки
  • 4 Внешние ссылки

Примеры

Рубин

Самоанализ типов - ключевая особенность Ruby. В Ruby, класс объекта (предком каждого класса) обеспечивает Object#instance_of?и Object#kind_of?методы проверки класса экземпляра. Последний возвращает истину, когда конкретный экземпляр, которому было отправлено сообщение, является экземпляром потомка рассматриваемого класса. Например, рассмотрим следующий пример кода (вы можете сразу же попробовать это с помощью Interactive Ruby Shell ):

$ irb irb(main):001:0gt; A=Class.new =gt; A irb(main):002:0gt; B=Class.new A =gt; B irb(main):003:0gt; a=A.new =gt; #lt;A:0x2e44b78gt; irb(main):004:0gt; b=B.new =gt; #lt;B:0x2e431b0gt; irb(main):005:0gt; a.instance_of? A =gt; true irb(main):006:0gt; b.instance_of? A =gt; false irb(main):007:0gt; b.kind_of? A =gt; true

В приведенном выше примере этот Classкласс используется как любой другой класс в Ruby. Создаются два класса, Aи Bпервый является суперклассом второго, затем проверяется по одному экземпляру каждого класса. Последнее выражение дает истину, потому что Aявляется суперклассом класса b.

Кроме того, вы можете напрямую запросить класс любого объекта и «сравнить» их (код ниже предполагает выполнение кода выше):

irb(main):008:0gt; A.instance_of? Class =gt; true irb(main):009:0gt; a.class =gt; A irb(main):010:0gt; a.class.class =gt; Class irb(main):011:0gt; A gt; B =gt; true irb(main):012:0gt; B lt;= A =gt; true

Цель-C

В Objective-C, например, и общий Object, и NSObject (в Cocoa / OpenStep ) предоставляют метод, isMemberOfClass: который возвращает истину, если аргумент метода является экземпляром указанного класса. Метод isKindOfClass:аналогичным образом возвращает истину, если аргумент наследуется от указанного класса.

Например, предположим, что у нас есть Appleи Orangeкласс, наследующий от Fruit.

Теперь в eatметоде мы можем написать

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

Теперь, когда eatвызывается с универсальным объектом (an id), функция будет вести себя правильно в зависимости от типа универсального объекта.

C ++

C ++ поддерживает самоанализ типов с помощью ключевых слов typeid и dynamic_cast информации о типах времени выполнения (RTTI). Выражение может быть использовано, чтобы определить, является ли конкретный объект конкретного производного класса. Например: dynamic_cast

Person* p = dynamic_castlt;Person *gt;(obj); if (p != nullptr) { p-gt;walk(); }

typeidОператор извлекает std::type_infoобъект, описывающий наиболее производный тип объекта:

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

Object Pascal

Самоанализ типов был частью Object Pascal с момента первоначального выпуска Delphi, который активно использует RTTI для визуального проектирования форм. В Object Pascal все классы происходят от базового класса TObject, который реализует базовые функции RTTI. На имя каждого класса можно ссылаться в коде для целей RTTI; идентификатор имени класса реализован как указатель на метаданные класса, которые можно объявить и использовать как переменную типа TClass. Язык включает оператор is, чтобы определить, является ли объект заданным классом или является его наследником, оператор as, обеспечивающий приведение типов с проверкой типа, и несколько методов TObject. Более глубокий самоанализ (перечисление полей и методов) традиционно поддерживается только для объектов, объявленных в состоянии $ M + (прагма), обычно TPersistent, и только для символов, определенных в опубликованном разделе. Delphi 2010 увеличил это почти до всех символов.

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 - это instanceofоператор. instanceofОператор определяет, принадлежит ли конкретный объект к определенному классу (или подкласса этого класса или класса, который реализует этот интерфейс). Например:

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

java.lang.ClassКласс является основой более продвинутого самоанализа.

Например, если желательно определить фактический класс объекта (а не то, является ли он членом определенного класса), Object.getClass()и Class.getName()можно использовать:

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

PHP

В PHP интроспекцию можно выполнить с помощью instanceofоператора. Например:

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

Perl

Самоанализ может быть достигнуто с помощью refи isaфункций в Perl.

Мы можем проанализировать следующие классы и их соответствующие экземпляры:

package Animal; sub new { my $class = shift; return bless {}, $class; } package Dog; use base 'Animal'; package main; my $animal = Animal-gt;new(); my $dog = Dog-gt;new();

с использованием:

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

Мета-объектный протокол

Гораздо более мощного самоанализа в Perl можно достичь с помощью объектной системы Moose и протокола Class::MOP метаобъектов ; Например, вы можете проверить, если данный объект делает на роль X:

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

Вот как вы можете перечислить полные имена всех методов, которые могут быть вызваны для объекта, вместе с классами, в которых они были определены:

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

Python

Наиболее распространенный метод интроспекции в Python - использование dirфункции для детализации атрибутов объекта. Например:

class Foo: def __init__(self, val): self.x = val def bar(self): return self.x
gt;gt;gt; dir(Foo(5)) ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'bar', 'x']

Кроме того, встроенные функции typeи isinstanceмогут использоваться для определения того, что представляет собой объект, в то время как hasattrмогут определять, что делает объект. Например:

gt;gt;gt; a = Foo(10) gt;gt;gt; b = Bar(11) gt;gt;gt; type(a) lt;type 'Foo'gt; gt;gt;gt; isinstance(a, Foo) True gt;gt;gt; isinstance(a, type(a)) True gt;gt;gt; isinstance(a, type(b)) False gt;gt;gt; hasattr(a, 'bar') True

ActionScript (as3)

В ActionScript функцию flash.utils.getQualifiedClassName можно использовать для получения имени класса / типа произвольного объекта.

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

В качестве альтернативы is можно использовать оператор, чтобы определить, принадлежит ли объект определенному типу:

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

Эту вторую функцию также можно использовать для проверки наследования родительских классов :

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

Самоанализ мета-типа

Как и Perl, ActionScript может пойти дальше, чем получение имени класса, но всех метаданных, функций и других элементов, составляющих объект, использующий flash.utils.describeType функцию; это используется при реализации отражения в 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));

Смотрите также

использованная литература

внешние ссылки

Последняя правка сделана 2023-08-11 05:43:38
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте