Из Википедии, свободной энциклопедии
  (Перенаправлено из Introspection (информатика) )
Перейти к навигации Перейти к поиску

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

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

Примеры [ править ]

Руби [ править ]

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

$ irb irb (main): 001: 0> A = Класс . new => A irb (main): 002: 0> B = Класс . Новый  => В IRB (основной): 003: 0> = . Новый => # <А: 0x2e44b78> IRB (основной): 004: 0> б = B . новое => # <B: 0x2e431b0> irb (основной): 005: 0> а . экземпляр? A => true irb (main): 006: 0> b . экземпляр? A => ложный irb (основной): 007: 0> b . Что-то вроде?   A => верно

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

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

IRB (основной): 008: 0> . экземпляр? Класс => истинный irb (основной): 009: 0> а . class => A irb (основной): 010: 0> a . класс . class => Класс irb (основной): 011: 0> A > B => true irb (main): 012: 0> B <= A => true     

Objective-C [ править ]

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

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

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

-  ( void ) eat: ( id ) sth  {  if  ([ sth  isKindOfClass : [ Fruit  class ]])  {  // мы действительно едим Fruit, поэтому продолжаем  if  ([ sth  isMemberOfClass : [ Apple  class ]])  {  eatApple ( стч );  }  иначе,  если  ([ sth  isMemberOfClass : [ класс апельсина  ]]) { eatOrange ( sth ); }    еще  {  ошибка ();  }  }  еще  {  ошибка ();  } }

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

C ++ [ править ]

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

Человек *  p  =  dynamic_cast < Person  *> ( obj ); если  ( p  ! =  nullptr )  {  p -> walk (); }

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

если  ( 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 увеличил это почти до всех символов.

процедура  Form1 . MyButtonOnClick ( Отправитель :  TObject ) ; var  aButton :  TButton ;  SenderClass :  TClass ; begin  SenderClass  : =  Отправитель . ClassType ;  // возвращает указатель класса отправителя ,  если  отправитель  является  TButton  затем  начать  aButton  : =  отправитель ,  как  TButton ;  EditBox . Текст  : =  aButton . Подпись ; // Свойство, которое есть у кнопки, но общие объекты не  заканчиваются  else  begin  EditBox . Текст  : =  Отправитель . ClassName ;  // возвращает имя класса отправителя в виде строки  end ; конец ;

Java [ править ]

Простейшим примером самоанализа типов в Java является оператор instanceof[1] . instanceofОператор определяет , принадлежит ли конкретный объект к определенному классу (или подкласса этого класса или класса , который реализует этот интерфейс). Например:

if  ( obj  instanceof  Person )  {  Person  p  =  ( Person ) obj ;  стр . прогулка (); }

Класс java.lang.Class[2] - это основа более продвинутого самоанализа.

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

Система . из . println ( объект . getClass (). getName ());

PHP [ править ]

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

if  ( $ obj  instanceof  Person )  {  // Делай что хочешь }

Perl [ править ]

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

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

пакет  Животное ; sub  новый  {  мой  $ class  =  shift ;  return  bless  {},  $ class ; }пакет  Dog ; использовать  базу  «Животное» ; основной пакет ; мой  $ animal  =  Животное -> новый (); мой  $ dog  =  Dog -> новый ();

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

напечатайте  "Это животное. \ n"  if  ref  $ animal  eq  'Animal' ; напечатайте  «Собака - это животное. \ n»,  если  $ dog -> isa ( 'Animal' );

Мета-объектный протокол [ править ]

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

if  ( $ object -> meta -> Does_role ( "X" ))  {  # сделать что-нибудь ... }

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

для  моего  $ метода  ( $ object -> meta -> get_all_methods )  {  print  $ method -> full_qualified_name ,  "\ n" ; }

Python [ править ]

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

класс  Foo :  def  __init__ ( self ,  val ):  self . x  =  val def  bar ( self ):  вернуть  себя . Икс
>>> dir ( Foo ( 5 )) ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__' , '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'bar', 'x']

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

>>> 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 , 'бар') Верно

ActionScript (as3) [ править ]

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

// все классы, используемые в as3, должны быть явно импортированы import  flash . утилит . getQualifiedClassName ; импортная  вспышка . дисплей . Спрайт ; // трассировка похожа на System.out.println в Java или эхо в трассировке PHP ( flash . utils . getQualifiedClassName ( "I'm a String" ));  // "String" следовые ( флеш . Utils . GetQualifiedClassName ( 1 ));  // "int", см. динамическое приведение, чтобы узнать, почему не Number trace( flash . utils . getQualifiedClassName ( новый  flash . display . Sprite ()));  // "flash.display.Sprite"

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

// трассировка похожа на System.out.println в Java или эхо в трассировке PHP ( «Я - строка»  - это  строка );  // истинная трассировка ( 1  -  строка );  // ложная трассировка ( «Я - строка»  - это  число );  // ложная трассировка ( 1  -  число );  // правда

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

импортная  вспышка . дисплей . DisplayObject ; импортная  вспышка . дисплей . Спрайт ;  // расширяет DisplayObjectтрассировка ( новая  вспышка . дисплей . Спрайт ()  - это  вспышка . дисплей . Спрайт );  // истинная трассировка ( новая  вспышка . display . Sprite ()  - это  flash . display . DisplayObject );  // true, потому что Sprite расширяет трассировку DisplayObject ( новый  flash . display . Sprite ()  is  String );  // ложный

Самоанализ мета-типа [ править ]

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

импортная  вспышка . утилит . descriptionType ; импортная  вспышка . утилит . getDefinitionByName ; импортная  вспышка . утилит . getQualifiedClassName ; импортная  вспышка . дисплей . Спрайт ;var  className : String  =  getQualifiedClassName ( новый  flash . display . Sprite ());  // "flash.display.Sprite" var  classRef : Class  =  getDefinitionByName ( className );  // Ссылка на класс flash.display {{Это не опечатка |.}} Sprite // например. 'new classRef ()' то же, что 'new flash.display.Sprite ()' trace ( describeType ( classRef ));  // возвращаем объект XML, описывающий тип // то же, что и: trace (describeType (flash.display.Sprite));

См. Также [ править ]

  • Реификация (информатика)
  • тип

Ссылки [ править ]

  1. ^ Спецификация языка Java: instanceof
  2. ^ Java API: java.lang.Class
  3. ^ Документация по мета-API Moose
  4. ^ Class :: MOP - протокол метаобъектов для Perl

Внешние ссылки [ править ]

  • Самоанализ на Rosetta кодекса