В інформатиці, рефлексія — це процес, під час якого комп'ютерна програма може відслідковувати і модифікувати власну структуру і поведінку під час виконання.
Це, кажучи простими словами, спосіб звернення програми до власного коду.
Історія
Перші комп'ютери були запрограмовані за допомогою їхньої нативної мови асемблер. Рефлексивність у ній була спадковою, оскільки ранні комп'ютери могли бути запрограмовані через визначення виконуваних інструкцій як даних та з використанням самомодифікуючого коду. Коли програмування дійшло до високорівневих мов програмування, таких як C, рефлексивна здатність зникнула (за межами Шкідливого програмного засобу), поки не з'явилися мови програмування з вбудованою рефлексією в їхні системи типізації.
Поняття рефлексії в мовах програмування ввів [en] в докторській дисертації 1982 р.
Використання
Рефлексія може використовуватися для спостерігання і зміни програми під час виконання. Рефлексивний компонент програми може спостерігати за виконанням певної частини коду і змінювати себе для досягнення потрібної цілі. Модифікація виконується під час виконання програми шляхом динамічної зміни коду.
В об'єктно-орієнтованих мовах програмування, таких як Java, рефлексія дозволяє огляд класів, інтерфейсів, полів і методів в період виконання програми, не знаючи імен інтерфейсів, полів, методів в період компіляції. Вона також дозволяє викликати методи.
Рефлексію можна застосовувати для динамічної адаптації програми до різноманітних ситуацій. Наприклад, розгляньмо програму, яка використовує два різні класи X
і Y
для виконання аналогічних операцій. Без рефлексії в коді програми методи класів X
і Y
будуть викликатися явно. Якщо програма спроектована з використанням рефлексно-орієнтованої парадигми програмування, деяка ділянка коду не буде містити явних викликів методів класів X
і Y
; програма виконає цю частину двічі: спочатку для класу X
, потім для класу Y
.
Рефлексія — це один з видів метапрограмування.
В деяких об'єктно-орієнтованих мовах програмування, таких як C# і Java, рефлексію можна використовувати для перевизначення ( правил доступу до методів класу). Наприклад, за допомогою рефлексії можна змінити значення поля з модифікатором доступу private
з стороннього класу.
Реалізація
Програми, котрі написані за допомогою тих мов програмування, які підтримують рефлексію, мають додаткові можливості, реалізація яких на низькорівневих мовах є доволі важкою. Перерахуємо деякі з них:
- пошук і модифікація конструкцій початковий коду (блоків, класів, методів, протоколів і т.д.) як об'єктів першого класу під час виконання;
- зміна імен класів і функцій під час виконання;
- аналіз і виконання стрічок коду, які надходять;
- створення інтерпретатора псевдокоду нової мови.
Ці можливості можна реалізовувати різними способами. У мові рефлексія є частиною щоденної ідіоми програмування. Всі методи, які викликаються, отримують в контексті інформацію про те, звідки вони були викликані, і посилання на об'єкти, до яких вони належать. Безпека контролюється програмно за допомогою стеку викликів: викликається callers() для отримання списку методів; перевіряється, чи не заблокував callers() сам себе.
Компільовані мови покладаються на свої системи виконання, які забезпечують програми інформацією про їхній початковий код. Скомпільований на Objective-C виконуваний файл, наприклад, записує імена всіх методів в один блок, створює таблицю відповідності. В компільованих мовах, які підтримують створення функцій під час виконання, таких як Common Lisp, середовище виконання має містити компілятор і інтерпретатор.
Реалізація рефлексії в мовах, які її не підтримують, виконується за допомогою системи трансформації програми для автоматичного відслідковування змін в початковому коді.
Приклади
Наступні приклади показують застосування рефлексії на прикладі створення екземпляру foo
класу Foo
і виклику метода hello
(абоHello
) в різних мовах програмування. Для кожної мови наведено два приклади: у першому не використовується рефлексія, а у другому використовується.
ECMAScript
Так само працює JavaScript і ActionScript:
//Без рефлексії new Foo().hello() // З рефлексією // assuming that Foo resides in this new this['Foo']()['hello']() // or without assumption new (eval('Foo'))()['hello']()
Java
// Без рефлексії new Foo().hello(); // З рефлексією Class foo = Class.forName("Foo"); foo.getMethod("hello", null).invoke(foo.newInstance(), null);
Qt/C++
Бібліотека Qt розширює можливості C++ за допомогою метамови й забезпечує підтримку рефлексії для посилання на члени/методи класу і запит імені об'єктів Qt за допомогою QMetaObject, що містить метадані про об'єкти Qt.
// Без рефлексії QObject *obj = new QPushButton; obj->metaObject()->className(); // "QPushButton" // З рефлексією QPushButton::staticMetaObject.className(); // "QPushButton"
Lua
-- Без рефлексії Foo.hello() -- З рефлексією _G['Foo']['hello']()
Objective-C
// Без рефлексії Foo *foo = [[Foo alloc] init]; [foo hello]; // З рефлексією Class cls = NSClassFromString(@"Foo"); id foo = [[cls alloc] init]; SEL selector = NSSelectorFromString(@"hello"); [foo performSelector:selector withObject:nil];
Perl
# Без рефлексії my $foo = Foo->new(); $foo->hello(); # З рефлексією (використовуючи синтаксис розіменування об'єктів) my $class = "Foo"; my $method = "hello"; my $object = $class->new(); $object->$method();
PHP
//Без рефлексії $oFoo = new Foo(); $oFoo->hello(); //З рефлексією (використовуючи ReflectionClass) $oReflector = new ReflectionClass('Foo'); $oFoo = $oReflector->newInstance(); $oHello = $oReflector->getMethod('hello'); $oHello->invoke($oFoo); //З рефлексією (використовуючи callback) $oFoo = new Foo(); call_user_func(array($oFoo,'hello')); //З рефлексією (використовуючи синтаксис розіменування об'єктів) $class_name = "Foo"; $f = new $class_name(); $method = "hello"; $f->$method();
Python
# Без рефлексії Foo().hello() # З рефлексією getattr(globals()['Foo'](), 'hello')()
Ruby
# Без рефлексії Foo.new.hello # З рефлексією Object.const_get(:Foo).send(:new).send(:hello)
Smalltalk
"Без рефлексії" Foo new hello "З рефлексією " ((Smalltalk at: #Foo) perform: #new) perform: #hello
Io
Foo := Object clone do( hello := method( "Hello" println ) ) # Без рефлексії Foo hello # З рефлексією getSlot("Foo") getSlot("hello") call
ActionScript 3.0
// Без рефлексії var foo:Foo = new Foo(); foo.hello(); // З рефлексією var cls:Object = getDefinitionByName("Foo"); var foo:Object = new cls(); foo["hello"]();
Delphi 2010
// Без рефлексії var foo : TFoo; begin foo := TFoo.Create(); foo.Hello(); end; // З рефлексією var c : TRttiContext; t : TRttiInstanceType; foo : TValue; begin c := TRttiContext.Create; t := (c.FindType('TFoo') as TRttiInstanceType); foo := t.GetMethod('Create').Invoke(t.MetaclassType,[]); t.GetMethod('Hello').Invoke(foo,[]); c.Free; end.
Примітки
- (PDF). Архів оригіналу (PDF) за 22 лютого 2016. Процитовано 2 червня 2015.
- Brian Cantwell Smith, Procedural Reflection in Programming Languages, Department of Electrical Engineering and Computer Science, Massachusetts Institute of Technology, PhD Thesis, 1982.
- . Архів оригіналу за 13 грудня 2015. Процитовано 2 червня 2015.
Література
- Forman, Ira R. and Forman, Nate. Java Reflection in Action. — Manning Publications Co, 2004. — .
- Forman, Ira R. and Danforth, Scott H. Putting Metaclasses to Work: A New Dimension in Object-oriented Programming. — Addison Wesley Longman Publishing Co., Inc, 1999. — .
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
V informatici refleksiya ce proces pid chas yakogo komp yuterna programa mozhe vidslidkovuvati i modifikuvati vlasnu strukturu i povedinku pid chas vikonannya Ce kazhuchi prostimi slovami sposib zvernennya programi do vlasnogo kodu IstoriyaPershi komp yuteri buli zaprogramovani za dopomogoyu yihnoyi nativnoyi movi asembler Refleksivnist u nij bula spadkovoyu oskilki ranni komp yuteri mogli buti zaprogramovani cherez viznachennya vikonuvanih instrukcij yak danih ta z vikoristannyam samomodifikuyuchogo kodu Koli programuvannya dijshlo do visokorivnevih mov programuvannya takih yak C refleksivna zdatnist zniknula za mezhami Shkidlivogo programnogo zasobu poki ne z yavilisya movi programuvannya z vbudovanoyu refleksiyeyu v yihni sistemi tipizaciyi Ponyattya refleksiyi v movah programuvannya vviv en v doktorskij disertaciyi 1982 r VikoristannyaRefleksiya mozhe vikoristovuvatisya dlya sposterigannya i zmini programi pid chas vikonannya Refleksivnij komponent programi mozhe sposterigati za vikonannyam pevnoyi chastini kodu i zminyuvati sebe dlya dosyagnennya potribnoyi cili Modifikaciya vikonuyetsya pid chas vikonannya programi shlyahom dinamichnoyi zmini kodu V ob yektno oriyentovanih movah programuvannya takih yak Java refleksiya dozvolyaye oglyad klasiv interfejsiv poliv i metodiv v period vikonannya programi ne znayuchi imen interfejsiv poliv metodiv v period kompilyaciyi Vona takozh dozvolyaye viklikati metodi Refleksiyu mozhna zastosovuvati dlya dinamichnoyi adaptaciyi programi do riznomanitnih situacij Napriklad rozglyanmo programu yaka vikoristovuye dva rizni klasi X i Ydlya vikonannya analogichnih operacij Bez refleksiyi v kodi programi metodi klasiv X i Y budut viklikatisya yavno Yaksho programa sproektovana z vikoristannyam refleksno oriyentovanoyi paradigmi programuvannya deyaka dilyanka kodu ne bude mistiti yavnih viklikiv metodiv klasiv X i Y programa vikonaye cyu chastinu dvichi spochatku dlya klasu X potim dlya klasu Y Refleksiya ce odin z vidiv metaprogramuvannya V deyakih ob yektno oriyentovanih movah programuvannya takih yak C i Java refleksiyu mozhna vikoristovuvati dlya pereviznachennya pravil dostupu do metodiv klasu Napriklad za dopomogoyu refleksiyi mozhna zminiti znachennya polya z modifikatorom dostupu private z storonnogo klasu RealizaciyaProgrami kotri napisani za dopomogoyu tih mov programuvannya yaki pidtrimuyut refleksiyu mayut dodatkovi mozhlivosti realizaciya yakih na nizkorivnevih movah ye dovoli vazhkoyu Pererahuyemo deyaki z nih poshuk i modifikaciya konstrukcij pochatkovij kodu blokiv klasiv metodiv protokoliv i t d yak ob yektiv pershogo klasu pid chas vikonannya zmina imen klasiv i funkcij pid chas vikonannya analiz i vikonannya strichok kodu yaki nadhodyat stvorennya interpretatora psevdokodu novoyi movi Ci mozhlivosti mozhna realizovuvati riznimi sposobami U movi refleksiya ye chastinoyu shodennoyi idiomi programuvannya Vsi metodi yaki viklikayutsya otrimuyut v konteksti informaciyu pro te zvidki voni buli viklikani i posilannya na ob yekti do yakih voni nalezhat Bezpeka kontrolyuyetsya programno za dopomogoyu steku viklikiv viklikayetsya callers dlya otrimannya spisku metodiv pereviryayetsya chi ne zablokuvav callers sam sebe Kompilovani movi pokladayutsya na svoyi sistemi vikonannya yaki zabezpechuyut programi informaciyeyu pro yihnij pochatkovij kod Skompilovanij na Objective C vikonuvanij fajl napriklad zapisuye imena vsih metodiv v odin blok stvoryuye tablicyu vidpovidnosti V kompilovanih movah yaki pidtrimuyut stvorennya funkcij pid chas vikonannya takih yak Common Lisp seredovishe vikonannya maye mistiti kompilyator i interpretator Realizaciya refleksiyi v movah yaki yiyi ne pidtrimuyut vikonuyetsya za dopomogoyu sistemi transformaciyi programi dlya avtomatichnogo vidslidkovuvannya zmin v pochatkovomu kodi PrikladiNastupni prikladi pokazuyut zastosuvannya refleksiyi na prikladi stvorennya ekzemplyaru foo klasu Foo i vikliku metoda hello aboHello v riznih movah programuvannya Dlya kozhnoyi movi navedeno dva prikladi u pershomu ne vikoristovuyetsya refleksiya a u drugomu vikoristovuyetsya ECMAScript Tak samo pracyuye JavaScript i ActionScript Bez refleksiyi new Foo hello Z refleksiyeyu assuming that Foo resides in this new this Foo hello or without assumption new eval Foo hello Java Bez refleksiyi new Foo hello Z refleksiyeyu Class foo Class forName Foo foo getMethod hello null invoke foo newInstance null Qt C Biblioteka Qt rozshiryuye mozhlivosti C za dopomogoyu metamovi j zabezpechuye pidtrimku refleksiyi dlya posilannya na chleni metodi klasu i zapit imeni ob yektiv Qt za dopomogoyu QMetaObject sho mistit metadani pro ob yekti Qt Bez refleksiyi QObject obj new QPushButton obj gt metaObject gt className QPushButton Z refleksiyeyu QPushButton staticMetaObject className QPushButton Lua Bez refleksiyi Foo hello Z refleksiyeyu G Foo hello Objective C Bez refleksiyi Foo foo Foo alloc init foo hello Z refleksiyeyu Class cls NSClassFromString Foo id foo cls alloc init SEL selector NSSelectorFromString hello foo performSelector selector withObject nil Perl Bez refleksiyi my foo Foo gt new foo gt hello Z refleksiyeyu vikoristovuyuchi sintaksis rozimenuvannya ob yektiv my class Foo my method hello my object class gt new object gt method PHP Bez refleksiyi oFoo new Foo oFoo gt hello Z refleksiyeyu vikoristovuyuchi ReflectionClass oReflector new ReflectionClass Foo oFoo oReflector gt newInstance oHello oReflector gt getMethod hello oHello gt invoke oFoo Z refleksiyeyu vikoristovuyuchi callback oFoo new Foo call user func array oFoo hello Z refleksiyeyu vikoristovuyuchi sintaksis rozimenuvannya ob yektiv class name Foo f new class name method hello f gt method Python Bez refleksiyi Foo hello Z refleksiyeyu getattr globals Foo hello Ruby Bez refleksiyi Foo new hello Z refleksiyeyu Object const get Foo send new send hello Smalltalk Bez refleksiyi Foo new hello Z refleksiyeyu Smalltalk at Foo perform new perform hello Io Foo Object clone do hello method Hello println Bez refleksiyi Foo hello Z refleksiyeyu getSlot Foo getSlot hello call ActionScript 3 0 Bez refleksiyi var foo Foo new Foo foo hello Z refleksiyeyu var cls Object getDefinitionByName Foo var foo Object new cls foo hello Delphi 2010 Bez refleksiyi var foo TFoo begin foo TFoo Create foo Hello end Z refleksiyeyu var c TRttiContext t TRttiInstanceType foo TValue begin c TRttiContext Create t c FindType TFoo as TRttiInstanceType foo t GetMethod Create Invoke t MetaclassType t GetMethod Hello Invoke foo c Free end Primitki PDF Arhiv originalu PDF za 22 lyutogo 2016 Procitovano 2 chervnya 2015 Brian Cantwell Smith Procedural Reflection in Programming Languages Department of Electrical Engineering and Computer Science Massachusetts Institute of Technology PhD Thesis 1982 Arhiv originalu za 13 grudnya 2015 Procitovano 2 chervnya 2015 LiteraturaForman Ira R and Forman Nate Java Reflection in Action Manning Publications Co 2004 ISBN 1932394184 Forman Ira R and Danforth Scott H Putting Metaclasses to Work A New Dimension in Object oriented Programming Addison Wesley Longman Publishing Co Inc 1999 ISBN 0 201 43305 2