Типа самоанализ - Type introspection
Эта статья поднимает множество проблем. Пожалуйста помоги Улучши это или обсудите эти вопросы на страница обсуждения. (Узнайте, как и когда удалить эти сообщения-шаблоны) (Узнайте, как и когда удалить этот шаблон сообщения)
|
Было высказано предположение, что тип быть слился в эту статью. (Обсудить) Предлагается с июля 2020 года. |
В вычисление, тип интроспекции способность программы к исследоватьто тип или свойства объект в время выполнения.Немного языки программирования обладают этой способностью.
Самоанализ не следует путать с отражение, что делает шаг вперед и дает возможность программе манипулировать значения, метаданные, свойства и функции объекта во время выполнения. Некоторые языки программирования также обладают такой способностью; например.,Ява,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));