Відображення (програмування)

Nuvola apps important recycle.svg
Ця стаття або розділ потребує переробки.
Будь ласка, поліпшите статтю відповідно до правилами написання статей.

В інформатики відображення або рефлексія (синонім інтроспекція, англ. reflection ) Означає процес, під час якого програма може відстежувати і модифікувати власну структуру і поведінку під час виконання. Парадигма програмування, покладена в основу відображення, називається рефлексивним програмуванням. Це один з видів метапрограмування [1].

У більшості сучасних комп'ютерних архітектур програмні інструкції (код) зберігаються як дані. Різниця між кодом і даними в тому, що виконуючи код, комп'ютери обробляють дані. Тобто інструкції виконуються, а дані обробляються так, як наказано цими інструкціями. Однак програми, написані за допомогою деяких мов, здатні обробляти власні інструкції як дані і виконувати, таким чином, рефлексивні модифікації. Такі самомодіфіцірующіеся програми в основному створюються за допомогою високорівневих мов програмування, що використовують віртуальні машини (наприклад, Smalltalk, скриптові мови). У меншій мірі рефлексія використовується в мовах з оголошують і / або статичними типами (наприклад, Java, Сі, ML, Haskell).


1. Рефлексивно-орієнтоване програмування

Рефлексивно-орієнтоване програмування, або рефлексивне програмування - функціональне розширення парадигми об'єктно-орієнтованого програмування. Рефлексивно-орієнтоване програмування включає в себе самоперевірку, самомодіфікаціі і самоклонірованіе. Тим не менш, головне достоїнство рефлексивно-орієнтованої парадигми полягає в динамічній модифікації програми, яка може бути визначена і виконана під час роботи програми. Деякі імперативні підходи, наприклад, процедурна і об'єктно-орієнтована парадигми програмування, вказують, що існує чітка зумовлена ​​послідовність операцій обробки даних. Парадигма рефлексивно-орієнтованого програмування, тим не менш, додає можливість динамічної модифікації програмних інструкцій під час роботи і їх виклику в модифікованому вигляді. Тобто програмна архітектура сама визначає, що саме можна робити під час роботи виходячи з даних, сервісів і специфічних операцій.


2. Історія

Поняття рефлексії в мовах програмування введено Brian Cantwell Smith в докторській дисертації 1982 [2] [3] поряд з поняттям meta-circular interpreter, як компонента 3-Lisp.


3. Застосування

Рефлексія може використовуватися для спостереження та зміни програми під час виконання. Рефлексивний компонент програми може спостерігати за виконанням певної ділянки коду і змінювати себе для досягнення бажаної мети. Модифікація виконується під час виконання програми шляхом динамічної зміни коду.

Рефлексію можна застосовувати і для динамічної адаптації програми до різних ситуацій. Наприклад, розглянемо програму, що використовує два різних класу X і Y для виконання аналогічних операцій. Без рефлексії в коді програми методи класів X і Y будуть викликатися явно. Якщо програма спроектована із застосуванням рефлексивно-орієнтований парадигми програмування, деякий ділянку коду не буде містити явних викликів методів класів X і Y; програма виконає цю ділянку двічі: спочатку для класу X, потім для класу Y.


4. Реалізації

Програми, написані на мовах програмування, що підтримують рефлексію, наділені додатковими можливостями, реалізація яких на мовах низького рівня скрутна. Перерахуємо деякі з них:

  • пошук і модифікація конструкцій вихідного коду (блоків, класів, методів, протоколів і т. п.) як об'єкт першого класу під час виконання;
  • зміна імен класів і функцій під час виконання;
  • аналіз і виконання рядків коду, що надходять ззовні;
  • створення інтерпретатора байткод нової мови.

Реалізація цих можливостей можлива різними шляхами. У мові MOO рефлексія є частиною щоденної ідіоми програмування. Всі викликаються методи отримують в контексті інформацію про те, звідки вони викликані, і посилання на об'єкти, до яких вони належать. Безпека контролюється програмно за допомогою стека викликів: викликається callers () для отримання списку методів; перевіряється, не заблокував Чи callers () [1] сам себе.

Компільовані мови покладаються на свої системи виконання, що забезпечують програми інформацією про їх вихідному коді. Скомпільований на Objective-C виконуваний файл, наприклад, записує імена всіх методів в один блок, створює таблицю відповідності. У компільованих мовах, що підтримують створення функцій під час виконання, таких як Common Lisp, середа виконання повинна включати компілятор і інтерпретатор.

Реалізація рефлексії на мовах, її не підтримують, виконується за допомогою системи трансформації програми для автоматичного відстеження змін вихідного коду.


5. Приклади

Наступні приклади ілюструють застосування рефлексії на прикладі створення екземпляра foo класу Foo і виклику методу hello (або Hello) в різних мовах програмування. Для кожної мови приведено по два приклади: перший не використовує рефлексію, а другий використовує.

5.1. C #

 / / Без рефлексії  new  Foo  (  )  .  Hello  (  )  ;  / / З рефлексією  Type type  =  System  .  Type  .  GetType  (  "Foo"  )  ;  var  foo  =  Activator  .  CreateInstance  (  type  )  ;  foo  .  GetType  (  )  .  GetMethod  (  "Hello"  )  .  Invoke  (  foo,  null  )  ; 

5.2. ECMAScript

Також працює на JavaScript і ActionScript :

 / / Без рефлексії  new  Foo  (  )  .  hello  (  )  / / З рефлексією  / / Assuming that Foo resides in this  new  this  [  'Foo'  ]  (  )  [  'Hello'  ]  (  )  / / Or without assumption  new  (  eval  (  'Foo'  )  )  (  )  [  'Hello'  ]  (  ) 

5.3. Java

 / / Без рефлексії  new  Foo  (  )  .  hello  (  )  ;  / / З рефлексією  Class  cls  =  Class  .  forName  (  "Foo"  )  ;  cls.  getMethod  (  "Hello"  ,  null  )  .  invoke  (  cls.  newInstance  (  )  ,  null  )  ; 

5.4. Qt / C + +

Бібліотека Qt розширює можливості C + + за допомогою метамови і забезпечує підтримку рефлексії для посилань на члени / методи класу і запит імені об'єктів Qt за допомогою класу QMetaObject, що містить метадані про об'єкти Qt.

 / / Без рефлексії  QObject  *  obj  =  new  QPushButton  ;  obj  -  >  metaObject  (  )  -  >  className  (  )  ;  / / "QPushButton"  / / З рефлексією  QPushButton  ::  staticMetaObject  .  className  (  )  ;  / / "QPushButton" 

5.5. Lua

 - Без рефлексії  Foo  .  hello  (  )  - З рефлексією  _G  [  'Foo'  ]  [  'Hello'  ]  (  ) 

5.6. 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  ]  ; 

5.7. Perl

 # Без рефлексії  my  $ Foo  =  Foo  ->  new  (  )  ;  $ Foo  ->  hello  (  )  ;  # З рефлексією  my  $ Class  =  "Foo"  ;  my  $ Method  =  "Hello"  ;  my  $ Object  =  $ Class  ->  new  (  )  ;  $ Object  ->  $ Method  (  )  ; 

5.8. PHP

 / / Без рефлексії  $ OFoo  =  new  Foo  (  )  ;  $ OFoo  ->  hello  (  )  ;  / / З рефлексією  $ 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  (  )  ; 

5.9. Python

 # Без рефлексії  Foo  (  )  .  hello  (  )  # З рефлексією  getattr  (  globals  (  )  [  'Foo'  ]  (  )  ,  'Hello'  )  (  ) 

5.10. Ruby

 # Без рефлексії  Foo.  new  .  hello  # З рефлексією  Object  .  const_get  (  : Foo  )  .  send  (  : New  )  .  send  (  : Hello  ) 

5.11. Smalltalk

 "Без рефлексії"  Foo  new hello  "З рефлексією"  (  (  Smalltalk  at:  # Foo  )  perform:  # New  )  perform:  # Hello 

5.12. Io

 Foo: =  Object  clone  do  (  hello: =  method  (  "Hello"  println  )  )  # Без рефлексії  Foo hello  # З рефлексією  getSlot  (  "Foo"  )  getSlot  (  "Hello"  )  call 

5.13. ActionScript 3.0

 / / Без рефлексії  var  foo: Foo =  new  Foo  (  )  ; Foo.  hello  (  )  ;  / / З рефлексією  var  cls:  Object  = GetDefinitionByName  (  "Foo"  )  ;  var  foo:  Object  =  new  cls  (  )  ; Foo.  [  "Hello"  ]  (  )  ; 

5.14. 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  .