В інформатиці відображення або рефлексія (холоним інтроспекції, англ. reflection) означає процес, під час якого програма може відслідковувати і модифікувати власну структуру і поведінку під час виконання. Парадигма програмування, покладена в основу відображення, називається рефлексивним програмуванням. Це один з видів метапрограммирования[].
У більшості сучасних комп'ютерних архітектур програмні інструкції (код) зберігаються як дані. Різниця між кодом і даними в тому, що виконуючи код, комп'ютери обробляють дані. Тобто інструкції виконуються, а дані обробляються так, як наказано цими інструкціями. Однак програми, написані з допомогою деяких мов, здатні обробляти власні інструкції як дані і виконувати, таким чином, рефлексивні модифікації. Такі самомодифицирующиеся програми в основному створюються з допомогою високорівневих мов програмування, що використовують віртуальні машини (наприклад, Smalltalk, скриптові мови). У меншій мірі рефлексія використовується у мовах з повідомляють і/або статичними типами (наприклад, Сі, ML, Haskell, F#).
Рефлексивно-орієнтоване програмування, або рефлексивне програмування — функціональне розширення парадигми об'єктно-орієнтованого програмування. Рефлексивно-орієнтоване програмування включає в себе самоперевірку, самомодификацию і самоклонирование. Тим не менш, головне достоїнство рефлексивно-орієнтованої парадигми полягає в динамічної модифікації програми, яка може бути визначена і виконана під час роботи програми. Деякі імперативні підходи, наприклад, процедурна та об'єктно-орієнтована парадигми програмування, вказують, що існує чітка визначена послідовність операцій обробки даних. Парадигма рефлексивно-орієнтованого програмування, тим не менш, додає можливість динамічної модифікації програмних інструкцій під час роботи та їх виклику в модифікованому вигляді. Тобто програмна архітектура сама визначає, що саме можна робити під час роботи виходячи з даних, сервісів і специфічних операцій.
Поняття рефлексії в мовах програмування введено Brian Cantwell Smith в докторській дисертації 1982 р.[] поряд з поняттям meta-circular interpreter, як компонента 3-Lisp.
Рефлексія може використовуватися для спостереження і зміни програми під час виконання. Рефлексивний компонент програми може спостерігати за виконанням певної ділянки коду і змінювати себе для досягнення бажаної мети. Модифікація виконується під час виконання програми шляхом динамічного зміни коду.
Рефлексію можна застосовувати і для динамічної адаптації програми до різних ситуацій. Наприклад, розглянемо програму, що використовує два різних класи X і Y для виконання аналогічних операцій. Без рефлексії в коді програми методи класів X і Y будуть викликатися явно. Якщо програма спроектована з застосуванням рефлексивно-орієнтованої парадигми програмування, деякий ділянку коду не буде містити явних викликів методів класів X і Y; програма виконає цю ділянку двічі: спочатку для класу X, потім для класу Y.
Програми, написані на мовах програмування, що підтримують рефлексію, наділені додатковими можливостями, реалізація яких на мовах низького рівня скрутна. Перерахуємо деякі з них: пошук і модифікація конструкцій вихідного коду (блоків, класів, методів, протоколів тощо) як об'єктів першого класу під час виконання; зміна імен класів і функцій під час виконання; аналіз та виконання рядків коду, що надходять ззовні; створення інтерпретатора байткода нової мови.
Реалізація цих можливостей можлива різними шляхами. У мові MOO рефлексія є частиною щоденної ідіоми програмування. Всі викликаються методи отримують в контексті інформацію про те, звідки вони викликані, і посилання на об'єкти, до яких вони належать. Безпека контролюється програмно за допомогою стека викликів: викликається callers() для отримання списку методів; перевіряється, не заблокував чи callers()[] сам себе.
Компилируемые мови покладаються на свої системи виконання, програми забезпечують інформацією про вихідному коді. Скомпільований на Objective-C виконуваний файл, наприклад, записує імена всіх методів в один блок, створює таблицю відповідності. У компилируемых мовах, які підтримують створення функцій під час виконання, таких як Common Lisp, середовище виконання повинна включати компілятор і інтерпретатор.
Реалізація рефлексії на мовах, які її не підтримують, виконується за допомогою системи трансформації програми для автоматичного відстеження змін вихідного коду.
Наступні приклади ілюструють застосування рефлексії на прикладі створення екземпляра foo класу Foo і виклику методу hello (або Hello) в різних мовах програмування. Для кожної мови наведено по два приклади: перший не використовує рефлексію, а другий використовує
C#
// Без рефлексії нова функція Foo().Привіт();
// З рефлексією Тип Тип = система.Тип.Метод Gettype("Фу"); вар фу = активатор.Властивість(типу); фу.Метод gettype().GetMethod("Привіт").Змінені(фу, нуль);
ECMAScript
Також працює на JavaScript, так і ActionScript для:
//Без рефлексії нова функція Foo().привіт()
// З рефлексією
// припустимо, що Foo проживає в даному це новий [ім'я Foo']()['привіт']()
// або без припущення новий (метод eval('Фу'))()['привіт']()
Java
// Без рефлексії нова функція Foo().привіт();
// З рефлексією Клас Foo = клас.forName("Фу"); фу.getMethod("Здрастуйте", NULL).змінені(фу.метод newinstance(), NULL);
Qt/C++
Бібліотека QT розширює можливості Сі++ з допомогою метаязыка і забезпечує підтримку рефлексії для посилань на члени/методи класу і запит імені об'єктів на QT класу функцію qmetaobject, що містить метадані про об'єкти на QT.
// Без рефлексії Спадкоємець qobject *ЦП = новий екземпляр об'єкта qpushbutton; параметр obj->функцію metaobject()->имя_класса(); // "кнопку qpushbutton"
// З рефлексією Кнопку qpushbutton::staticMetaObject.имя_класса(); // "кнопку qpushbutton"
//З рефлексією (використовуючи синтаксис разыменовывания об'єктів) $имя_класса = "Фу"; $Ф = новий $имя_класса(); метод $ = "привіт"; $Ф->$метод();
Python
# Без рефлексії Функція Foo().привіт()
# З рефлексією getattr(глобаль()['Foo' вище](), 'привіт')()
Ruby
# Без рефлексії Фу.нові.привіт
# З рефлексією Об'єкт.const_get(:Фу).відправити (новий).відправити(:привіт)
Smalltalk
"Без рефлексії" Фу новий привіт
"З рефлексією" (У мові smalltalk: #Фу) виконати: #новий) виконати: #привіт
Io
Фу := об'єкт клону зробити( привіт := метод( "Здрастуйте" код println ) )
# Без рефлексії Фу Привіт!
# З рефлексією getSlot("Фу") getSlot("привіт") телефонуйте
ActionScript 3.0
// Без рефлексії вар фу-Фу = новий файл Foo(); фу.привіт();
// З рефлексією вар ЦБС:об'єкт = getDefinitionByName("Фу"); вар фу:об'єкт = новий автомобіль CLS(); фу["привіт"]();
Delphi 2010
// Без рефлексії вар функція Foo : TFoo; почати фу := TFoo.Створити(); фу.Привіт(); кінець;
// З рефлексією вар з : TRttiContext; т : TRttiInstanceType; фу : TValue; почати с := TRttiContext.Створити; т := (АР.FindType('TFoo') як TRttiInstanceType); фу := т. GetMethod('Створити').Змінені(т. MetaclassType,[]); т. GetMethod('Привіт').Змінені(фу,[]); АР.Безкоштовно; кінець.