Рефлексия (программирование) (Jyslytvnx (hjkijgbbnjkfguny))
Рефлексия (отражение; холоним интроспекции, англ. reflection) — процесс, во время которого программа может отслеживать и модифицировать собственную структуру и поведение во время выполнения. Парадигма программирования, положенная в основу рефлексии, является одной из форм метапрограммирования[1] и называется рефлексивным программированием.
Во время выполнения программных инструкций (кода) компьютеры обрабатывают данные, что приводит к их изменению, при этом компьютеры не изменяют код. Однако в большинстве современных компьютерных архитектур код хранится как данные, и в некоторых языках программирования реализована возможность обрабатывать собственный код как данные, что приводит к изменению уже самого кода во время его выполнения. Такие самоизменяющиеся программы в основном создаются с помощью высокоуровневых языков программирования, использующих виртуальные машины (например, Smalltalk, скриптовые языки). В меньшей степени рефлексия используется в языках с объявляемыми или статическими типами (например, Си, ML, Haskell, F#).
Понятие рефлексии в языках программирования введено Брайаном Смитом (Brian Cantwell Smith) в докторской диссертации 1982 года[2][3] наряду с понятием метациркулярного вычислителя (англ. Meta-circular evaluator) как компонента 3-Lisp.
Рефлексивно-ориентированное программирование
[править | править код]Рефлексивно-ориентированное программирование, или рефлексивное программирование, — функциональное расширение парадигмы объектно-ориентированного программирования. Рефлексивно-ориентированное программирование включает в себя самопроверку, самомодификацию и самоклонирование. Тем не менее главное достоинство рефлексивно-ориентированной парадигмы заключается в динамической модификации программы, которая может быть определена и выполнена во время работы программы. Некоторые императивные подходы, например процедурная и объектно-ориентированная парадигмы программирования, указывают, что существует четкая предопределённая последовательность операций обработки данных. Парадигма рефлексивно-ориентированного программирования, тем не менее, добавляет возможность динамической модификации программных инструкций во время работы и их вызова в модифицированном виде. То есть программная архитектура сама определяет, что именно можно делать во время работы исходя из данных, сервисов и специфических операций.
Применение
[править | править код]Рефлексия может использоваться для наблюдения и изменения программы во время выполнения. Рефлексивный компонент программы может наблюдать за выполнением определённого участка кода и изменять себя для достижения желаемой цели. Модификация выполняется во время выполнения программы путём динамического изменения кода.
Рефлексию можно применять и для динамической адаптации программы к различным ситуациям. Например, рассмотрим программу, использующую два разных класса X
и Y
для выполнения аналогичных операций. Без рефлексии в коде программы методы классов X
и Y
будут вызываться явно. Если программа спроектирована с применением рефлексивно-ориентированной парадигмы программирования, некоторый участок кода не будет содержать явных вызовов методов классов X
и Y
; программа выполнит этот участок дважды: сначала для класса X
, затем для класса Y
.
Примером, проясняющим преимущества рефлексии, может служить Сериализация объекта в JSON. Без рефлексии необходимо было бы явным образом указывать все имена полей класса и ссылаться на их значения для сериализации. Но рефлексия позволяет программе самой определить все имеющиеся поля и получить их текстовые имена. Таким образом, сериализация становится доступна для любого объекта без написания лишнего кода.
Реализации
[править | править код]Программы, написанные на языках программирования, поддерживающих рефлексию, наделены дополнительными возможностями, реализация которых на языках низкого уровня затруднительна. Перечислим некоторые из них:
- поиск и модификация конструкций исходного кода (блоков, классов, методов, интерфейсов (протоколов) и т. п.) как объектов первого класса во время выполнения;
- изменение имён классов и функций во время выполнения;
- анализ и выполнение строк кода, поступающих извне;
- создание интерпретатора байткода нового языка.
Реализованы эти возможности могуть быть разными путями. В языке MOO рефлексия является частью ежедневной идиомы программирования. Все вызываемые методы получают в контексте информацию о том, откуда они вызваны, и ссылки на объекты, к которым они принадлежат. Безопасность контролируется программно с помощью стека вызовов: вызывается callers() для получения списка методов; проверяется, не заблокировал ли callers()[1] сам себя.
Компилируемые языки полагаются на свои среды выполнения, обеспечивающие программы информацией об их исходном коде. Скомпилированный на Objective-C выполняемый файл, например, записывает имена всех методов в один блок, создаёт таблицу соответствия. В компилируемых языках, поддерживающих создание функций во время выполнения, таких как Common Lisp, среда выполнения должна включать компилятор и интерпретатор.
Реализация рефлексии на языках, её не поддерживающих, выполняется с помощью системы трансформации программы для автоматического отслеживания изменений исходного кода.
Примеры
[править | править код]Пример на C#, в котором создаётся экземпляр foo
класса Foo
и осуществляется вызов метода Hello
, не использующий рефлексию и использующий её:
// Без рефлексии
new Foo().Hello();
// С рефлексией
Type type = System.Type.GetType("Foo");
var foo = Activator.CreateInstance(type);
foo.GetType().GetMethod("Hello").Invoke(foo, null);
Аналогичный пример для ECMAScript, JavaScript и ActionScript:
// Без рефлексии
new Foo().hello()
// С рефлексией
// с допущением, что Foo лежит в this
new this['Foo']()['hello']()
// без допущений
new (eval('Foo'))()['hello']()
Примечания
[править | править код]- ↑ Руководство Мета Халлбата англ. Matt Hurlbutt по поведенческой рефлексии и её реализации (англ.)
- ↑ , кандидатская диссертация, «Процедурная рефлексия в языках программирования», Массачусетский технологический институт, факультет электротехники и информатики, 1982 (англ.)
- ↑ Brian C. Smith. Рефлексия и семантики в процедурных языках программирования. Служебный отчёт MIT-LCS-TR-272, Массачусетский технологический институт, Кембридж, Mass., январь 1982 (англ.) . Дата обращения: 15 января 2011. Архивировано из оригинала 13 декабря 2015 года.
Литература
[править | править код]- Forman, 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.
Ссылки
[править | править код]- Jonathan M. Sobel and Daniel P. Friedman. An Introduction to Reflection-Oriented Programming (1996), Indiana University.
- Reflection in logic, functional and object-oriented programming: a short comparative study Архивная копия от 5 декабря 2006 на Wayback Machine
- An Introduction to Reflection-Oriented Programming
- Brian Foote’s pages on Reflection in Smalltalk Архивная копия от 27 ноября 2020 на Wayback Machine
- Java Reflection Tutorial Архивная копия от 27 февраля 2009 на Wayback Machine from Sun Microsystems
Для улучшения этой статьи желательно:
|
Эта статья или раздел нуждается в переработке. |