Интроспекция (программирование) — Википедия

Интроспекция (англ. type introspection) в программировании — возможность запросить тип и структуру объекта во время выполнения программы. Особое значение имеет в языке Objective C, однако имеется почти во всех языках, позволяющих манипулировать типами объектов как объектами первого класса. Следующие языки программирования поддерживают интроспекцию — C++RTTI), C#, Go, Java, Kotlin, JavaScript, DelphiRTTI), Perl, Ruby, Smalltalk, PHP и Python. Интроспекция может использоваться для реализации ad-hoc-полиморфизма.

C++ поддерживает интроспекцию благодаря динамическому определению типа с помощью оператора typeid, а также благодаря dynamic cast.

Оператор dynamic_cast может быть использован, чтобы определить, принадлежит ли объект иерархии определённого класса. Например:

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

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

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

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

if(p is Person) {    var person = p as Person; } 

В Java механизм интроспекции реализуется с помощью оператора instanceof[1]. instanceof определяет, принадлежит ли объект данному классу, классу-потомку или реализует ли объект данный интерфейс. Например:

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

Класс java.lang.Class[2] позволяет получить доступ к более качественной интроспекции.

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

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

В Python интроспекция может быть функционально реализована с помощью встроенных методов type() и dir() или встроенного модуля inspect, либо идти непосредственно от имени объекта с помощью встроенных аттрибутов __class__ и __dict__. Пользоваться интроспекцией в Python особенно удобно, благодаря парадигме, что "всё является объектом". Любая сущность, являясь объектом, имеет метаданные (данные об объекте), называемые аттрибутами, и связаные с этой сущностью функциональности, называемые методами. В Python новый класс по-умолчанию является сам по себе объектом метакласса type.

class MetaPerson(type):     def __repr__(cls):         return "Person"  class Person(metaclass=MetaPerson):     def __init__(self, name, age, friends = []):         self.name = name         self.age = age         self.friends = friends      def get_friends(self):         return self.friends 

В итоге интроспекция класса Person может быть интерпретирована следующим образом

>>> # Создание объекта ранее определённого класса Person >>> ivan = Person("Ivan", 26) >>> type(ivan) <class 'Person'> >>> type(Person) <class '__main__.MetaPerson'> >>> # видно, что имя Person является экземпляром метакласса MetaPerson >>> type(getattr(Person, 'get_friends')) <class 'function'> >>> isinstance(ivan, Person) True 

Любой объект имеет аттрибут __class__ возвращающий экземпляр соответствующего метакласса и __dict__ возвращающий словарь всех аттрибутов данного объекта. Методы, определённые в классе, становятся аттрибутами экземпляра соответствующего метакласса, поэтому их можно увидеть вызвав __dict__ от имени класса.

>>> ivan.__class__ <class 'Person'> >>> ivan.__dict__ {'name': 'Ivan', 'age': 26, 'friends': []} >>> {k: v.__class__ for k, v in ivan.__dict__.items()} {'name': str, 'age': int, 'friends': list} 

Примечания

[править | править код]
  1. Java Language Specification: instanceof. Дата обращения: 3 мая 2016. Архивировано 13 февраля 2012 года.
  2. Java API: java.lang.Class. Дата обращения: 3 мая 2016. Архивировано 11 сентября 2009 года.