Рефлексия (программирование): различия между версиями
[непроверенная версия] | [непроверенная версия] |
Tretyak (обсуждение | вклад) Нет описания правки |
|||
Строка 197: | Строка 197: | ||
var foo:Object = new cls(); |
var foo:Object = new cls(); |
||
foo.hello(); |
foo.hello(); |
||
</source> |
|||
===Delphi 2010=== |
|||
<source lang="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. |
|||
</source> |
</source> |
||
Версия от 15:23, 12 апреля 2011
В статье не хватает ссылок на источники (см. рекомендации по поиску). |
Эта статья или раздел нуждается в переработке. |
В информатике, отражение или рефлексия (синоним интроспекция, англ. reflection) означает процесс, во время которого программа может отслеживать и модифицировать собственную структуру и поведение во время выполнения. Парадигма программирования, положенная в основу отражения, называется рефлексивным программированием. Это один из видов метапрограммирования [1].
В большинстве современных компьютерных архитектур программные инструкции (код) хранятся как данные. Разница между кодом и данными в том, что выполняя код, компьютеры обрабатывают данные. То есть, 'инструкции' 'выполняются', а 'данные' 'обрабатываются' так, как предписано этими инструкциями. Однако, программы, написанные с помощью некоторых языков, способны обрабатывать собственные инструкции как данные и, таким образом, выполнять рефлексивные модификации. Такие самомодифицирующиеся программы в основном создаются с помощью высокоуровневых языков программирования, использующих виртуальные машины (например, Smalltalk, скриптовые языки). Также рефлексия используется в языках с объявляемыми и/или статическими типами (например, Java, Си, ML, Haskell).
Рефлексивно-ориентированное программирование
Рефлексивно-ориентированное программирование или рефлексивное программирование — функциональное расширение парадигмы объектно-ориентированного программирования. Рефлексивно-ориентированное программирование включает в себя самопроверку, самомодификацию и самоклонирование. Тем не менее, главное достоинство рефлексивно-ориентированной парадигмы заключается в динамической модификации программы, которое может быть определено и выполнено во время работы программы. Некоторые императивные подходы, например, процедурная и объектно-ориентированная парадигмы программирования, указывают, что существует четкая предопределённая последовательность операций обработки данных. Парадигма рефлексивно-ориентированного программирования, тем не менее, добавляет возможность динамической модификации программных инструкций во время работы и их вызова в модифицированном виде. То есть, программная архитектура сама определяет что именно можно делать во время работы исходя из данных, сервисов и специфических операций.
История
Понятие рефлексии в языках программирования введено Brian Cantwell Smith в докторской диссертации 1982 г. [2] [3] наряду с понятием meta-circular interpreter, как компонента 3-Lisp.
Применение
Рефлексия может использоваться для наблюдения и изменения программы во время выполнения. Рефлексивный компонент программы может наблюдать за выполнением определённого участка кода и изменять себя для достижения желаемой цели. Модификация выполняется во время выполнения программы путём динамического изменения кода.
Рефлексию можно применять и для динамической адаптации программы к различным ситуациям. Например, рассмотрим программу, использующую два разных класса X
и Y
для выполнения аналогичных операций. Без рефлексии в коде программы методы классов X
и Y
будут вызываться явно. Если программа спроектирована с применением рефлексивно-ориентированный прадигмы программирования, некоторый участок кода не будет содержать явных вызовов методов классов X
и Y
; программа выполнит этот участок дважды: сначала для класса X
, затем для класса Y
.
Реализации
Программы, написанные на языках программирования, поддерживающих рефлексию, наделены дополнительными возможностями, реализация которых на языках низкого уровня затруднительна. Перечислим некоторые из них:
- поиск и модификация конструкций исходного кода (блоков, классов, методов, протоколов и т. п.) как first-class object во время выполнения;
- изменение имён классов и функций во время выполнения;
- анализ и выполнение строк кода, поступающих извне;
- создание интерпретатора байткода нового языка.
Реализация этих возможностей возможна разными путями. В языке MOO, рефлексия является частью ежедневной идиомы программирования. Все вызываемые методы получают в контексте информацию о том, откуда они вызваны, и ссылки на объекты, к которым они принадлежат. Безопасность контролируется программно с помощью стека вызовов: вызывается callers() для получения списка методов; проверяется, не заблокировал ли callers()[1] сам себя.
Компилируемые языки полагаются на свои системы выполнения, обеспечивающие программы информацией о их исходном коде. Скомпилированный на Objective-C выполняемый файл, например, записывает имена всех методов в один блок, создаёт таблицу соответствия. В компилируемых языках, поддерживающих создание функций во время выполнения, таких как Common Lisp, среда выполнения должна включать компилятор и интерпретатор.
Реализация рефлексии на языках, её не поддерживающих, выполняется с помощью системы трансформации программы для автоматического отслеживания изменений исходного кода.
Примеры
Следующие примеры иллюстрируют применение рефлексии на примере создания экземпляра foo
класса Foo
и вызова метода hello
(или Hello
) в различных языках программирования. Для каждого языка приведено по два примера: первый не использует рефлексию, а второй использует.
C#
// Без рефлексии
Foo foo = new Foo();
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()
// С рефлексией
// assuming that Foo resides in this
new this['Foo']()['hello']()
// or without assumption
new (eval('Foo'))()['hello']()
Java
// Без рефлексии
new Foo().hello();
// С рефлексией
Class cls = Class.forName("Foo");
cls.getMethod("hello", null).invoke(cls.newInstance(), null);
Qt/C++
Библиотека Qt расширяет возможности C++ с помощью мета языка и обеспечивает поддержку рефлексии для ссылок на члены/методы класса и запрос имени объектов Qt с помощью класса QMetaObject, содержащего мета данные о объектах Qt.
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();
//С рефлексией
$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.
См. также
- en:Type introspection
- Самомодифицирующийся код
- Парадигма программирования
- Список рефлективных языков программирования
Ссылки
Notes
- ↑ Руководство Мета Халлбата англ. Matt Hurlbutt по поведенческой рефлексии и её реализации (англ.)
- ↑ , кандидатская диссертация, "Процедурная рефлексия в языках программирования", Массачусетский технологический институт, факультет электротехники и информатики, 1982 (англ.)
- ↑ Brian C. Smith. Рефлексия и семантики в процедурных языках программирования. Служебный отчёт MIT-LCS-TR-272, Массачусетский технологический институт, Кембридж, Mass., январь 1982 (англ.)
Documents
- Jonathan M. Sobel and Daniel P. Friedman. An Introduction to Reflection-Oriented Programming (1996), Indiana University.
Дополнительная информация
- Ira R. Forman and Nate Forman, Java Reflection in Action (2005), ISBN 1932394184
- Ira R. Forman and Scott Danforth, Putting Metaclasses to Work (1999), ISBN 0-201-43305-2
Внешние ссылки
- Reflection in logic, functional and object-oriented programming: a short comparative study
- An Introduction to Reflection-Oriented Programming
- Brian Foote's pages on Reflection in Smalltalk
- Java Reflection Tutorial from Sun Microsystems
int main()
{
printf("Hi");
return 0;
}
| Это заготовка статьи о программировании. Помогите Википедии, дополнив её. |