Интроспекция (англ. type introspection) в программировании — возможность запросить тип и структуру объекта во время выполнения программы. Особое значение имеет в языке Objective C, однако имеется почти во всех языках, позволяющих манипулировать типами объектов как объектами первого класса. Следующие языки программирования поддерживают интроспекцию — C++ (с RTTI), C#, Go, Java, Kotlin, JavaScript, Delphi (с RTTI), Perl, Ruby, Smalltalk, PHP и Python. Интроспекция может использоваться для реализации ad-hoc-полиморфизма.
Примеры
C++
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#
В C# для определения типа объекта во время исполнения используется метод GetType, а также ключевые слова is и as:
if(p is Person){ var person = p as Person;}Java
В 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
В 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=nameself.age=ageself.friends=friendsdef get_friends(self):returnself.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__fork,vinivan.__dict__.items()}{'name':str,'age':int,'friends':list}Примечания
- ↑Java Language Specification: instanceof. Дата обращения: 3 мая 2016. Архивировано 13 февраля 2012 года.
- ↑Java API: java.lang.Class. Дата обращения: 3 мая 2016. Архивировано 11 сентября 2009 года.