Интроспекция (психология)
- 1 year ago
- 0
- 0
Интроспекция ( англ. type introspection ) в программировании — возможность запросить тип и структуру объекта во время выполнения программы. Особое значение имеет в языке Objective C , однако имеется почти во всех языках, позволяющих манипулировать типами объектов как объектами первого класса . Следующие языки программирования поддерживают интроспекцию — C++ (с RTTI ), C# , Go , Java , Kotlin , JavaScript , Delphi (с RTTI ), 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
.
instanceof
определяет, принадлежит ли объект данному классу, классу-потомку или реализует ли объект данный интерфейс. Например:
if(obj instanceof Person){
Person p = (Person)obj;
p.walk();
}
Класс
java.lang.Class
позволяет получить доступ к более качественной интроспекции.
Например, если нужно определить точно тип объекта, можно воспользоваться методами
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}