Типа самоанализ - Type introspection

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

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

Примеры

Рубин

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

$ irbirb (основной): 001: 0>А=Класс.новый=> Аirb (основной): 002: 0>B=Класс.новый А=> Birb (основной): 003: 0>а=А.новый=> # irb (основной): 004: 0>б=B.новый=> # irb (основной): 005: 0>а.случай? А=> правдаirb (основной): 006: 0>б.случай? А=> ложьirb (основной): 007: 0>б.Что-то вроде? А=> правда

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

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

irb (основной): 008: 0>А.случай? Класс=> правдаirb (основной): 009: 0>а.класс=> Аirb (основной): 010: 0>а.класс.класс=> Классirb (основной): 011: 0>А > B=> правдаirb (основной): 012: 0>B <= А=> правда

Цель-C

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

Например, скажем, у нас есть яблоко и оранжевый класс, наследующий от Фрукты.

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

- (пустота)есть:(мне бы)что-то {    если ([что-то isKindOfClass:[Фрукты класс]]) {        // мы на самом деле едим фрукт, так что продолжаем        если ([что-то isMemberOfClass:[яблоко класс]]) {            есть яблоко(что-то);        } еще если ([что-то isMemberOfClass:[оранжевый класс]]) {            есть апельсин(что-то);        } еще {            ошибка();        }    } еще {        ошибка();    }}

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

C ++

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

Человек* п = dynamic_cast<Человек *>(объект);если (п != nullptr) {  п->ходить();}

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

если (типичный(Человек) == типичный(*объект)) {  serialize_person( объект );}

Object Pascal

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

процедура Форма 1.MyButtonOnClick(Отправитель: TObject);вар   кнопка: TButton;   SenderClass: TClass;начать   SenderClass := Отправитель.ClassType; // возвращает указатель на класс отправителя   если отправитель является TButton тогда   начать      кнопка := отправитель так как TButton;      EditBox.Текст := кнопка.Заголовок; // Свойство, которое есть у кнопки, но у обычных объектов нет   конец   еще начать      EditBox.Текст := Отправитель.ClassName; // возвращает имя класса отправителя в виде строки   конец;конец;

Ява

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

если (объект случай Человек) {    Человек п = (Человек)объект;    п.ходить();}

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

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

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

PHP

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

если ($ obj случай Человек) {    // Делай что хочешь}

Perl

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

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

пакет Животное;суб новый {    мой $ класс = сдвиг;    вернуть благослови {}, $ класс;}пакет Собака;использовать база 'Животное';пакет основной;мой $ животное = Животное->новый();мой $ собака = Собака->новый();

с помощью:

Распечатать "Это животное.  N" если ссылка $ животное экв 'Животное';Распечатать "Собака - это животное.  N" если $ собака->это('Животное');

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

Гораздо более мощного самоанализа в Perl можно достичь с помощью лось объектная система[3] и Класс :: СС мета-объект протокол;[4] например, вы можете проверить, делает а роль Икс:

если ($ объект->мета->делает_роль("ИКС")) {    # сделай что-нибудь ...}

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

для мой $ метод ($ объект->мета->get_all_methods) {    Распечатать $ метод->full_qualified_name, " п";}

Python

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

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

Также встроенные функции тип и это экземпляр может использоваться, чтобы определить, что за объект является в то время как hasattr может определить, что за объект делает. Например:

>>> а = Фу(10)>>> б = Бар(11)>>> тип(а)<type 'Foo'>>>> это экземпляр(а, Фу)Правда>>> это экземпляр(а, тип(а))Правда>>> это экземпляр(а, тип(б))Ложь>>> hasattr(а, 'бар')Правда

ActionScript (as3)

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

// все классы, используемые в as3, должны быть импортированы явноимпорт вспышка.утилиты.getQualifiedClassName;импорт вспышка.дисплей.Спрайт;// трассировка похожа на System.out.println в Java или echo в PHPслед(вспышка.утилиты.getQualifiedClassName("Я струна")); // "Строка"след(вспышка.утилиты.getQualifiedClassName(1)); // "int", почему не Number, см. динамическое приведениеслед(вспышка.утилиты.getQualifiedClassName(новый вспышка.дисплей.Спрайт())); // "flash.display.Sprite"

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

// трассировка похожа на System.out.println в Java или echo в PHPслед("Я струна" является Строка); // правдаслед(1 является Строка); // ложныйслед("Я струна" является Число); // ложныйслед(1 является Число); // правда

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

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

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

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

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

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

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

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