Светоотражающее программирование

редактировать
Не путать с Reflection (компьютерная графика).
Парадигмы программирования

В информатике, отражающее программирование или отражение является способность процесса исследовать, Introspect и изменять свою структуру и поведение.

СОДЕРЖАНИЕ
  • 1 Историческая справка
  • 2 использования
  • 3 Реализация
  • 4 Соображения безопасности
  • 5 примеров
    • 5.1 C #
    • 5.2 Delphi / Object Pascal
    • 5,3 эС
    • 5.4 Перейти
    • 5.5 Java
    • 5.6 JavaScript
    • 5.7 Юлия
    • 5.8 Цель-C
    • 5.9 Perl
    • 5.10 PHP
    • 5.11 Python
    • 5.12 R
    • 5.13 Рубин
    • 5.14 Ксоджо
  • 6 См. Также
  • 7 ссылки
    • 7.1 Цитаты
    • 7.2 Источники
  • 8 Дальнейшее чтение
  • 9 Внешние ссылки
Историческое прошлое

Самые ранние компьютеры были запрограммированы на своих родных языках ассемблера, которые по своей сути были рефлексивными, поскольку эти оригинальные архитектуры можно было программировать, определяя инструкции как данные и используя самомодифицирующийся код. Поскольку основная часть программирования перешла на компилируемые языки более высокого уровня, такие как Algol, Cobol, Fortran, Pascal и C, эта способность к отражению в значительной степени исчезла, пока не появились новые языки программирования с отражением, встроенным в их системы типов.

В докторской диссертации Брайана Кантуэлла Смита 1982 г. было введено понятие вычислительной рефлексии в процедурных языках программирования и понятие мета-кругового интерпретатора как компонента 3-Lisp.

Использует

Reflection помогает программистам создавать универсальные программные библиотеки для отображения данных, обработки различных форматов данных, выполнения сериализации или десериализации данных для обмена данными или объединения и разделения данных для контейнеров или пакетов данных.

Для эффективного использования отражения почти всегда требуется план: структура дизайна, описание кодировки, библиотека объектов, карта базы данных или отношения сущностей.

Отражение делает язык более подходящим для сетевого кода. Например, он помогает таким языкам, как Java, хорошо работать в сетях, обеспечивая библиотеки для сериализации, объединения и изменения форматов данных. Языки без отражения, такие как C, необходимы для использования вспомогательных компиляторов для таких задач, как абстрактная синтаксическая нотация, для создания кода для сериализации и объединения.

Отражение можно использовать для наблюдения и изменения выполнения программы во время выполнения. Программный компонент, ориентированный на отражение, может отслеживать выполнение вложения кода и может изменять себя в соответствии с желаемой целью этого вложения. Обычно это достигается путем динамического присвоения программного кода во время выполнения.

В объектно-ориентированных языках программирования, таких как Java, отражение позволяет проверять классы, интерфейсы, поля и методы во время выполнения, не зная имен интерфейсов, полей и методов во время компиляции. Он также позволяет создавать экземпляры новых объектов и вызывать методы.

Отражение часто используется как часть тестирования программного обеспечения, например, для создания / создания экземпляров фиктивных объектов во время выполнения.

Отражение также является ключевой стратегией метапрограммирования.

В некоторых объектно-ориентированных языках программирования, таких как C # и Java, отражение можно использовать для обхода правил доступности членов. Для свойств C # это может быть достигнуто путем записи непосредственно в (обычно невидимое) поле поддержки закрытого свойства. Также возможно найти закрытые методы классов и типов и вызвать их вручную. Это работает как для внутренних файлов проекта, так и для внешних библиотек, таких как сборки.NET и архивы Java.

Реализация

Язык, поддерживающий отражение, предоставляет ряд функций, доступных во время выполнения, которые иначе было бы трудно реализовать на языке более низкого уровня. Некоторые из этих функций позволяют:

  • Обнаруживайте и изменяйте конструкции исходного кода (такие как блоки кода, классы, методы, протоколы и т. Д.) Как первоклассные объекты во время выполнения.
  • Преобразуйте строку, соответствующую символическому имени класса или функции, в ссылку или вызов этого класса или функции.
  • Оцените строку, как если бы она была оператором исходного кода во время выполнения.
  • Создайте новый интерпретатор для байт-кода языка, чтобы придать новое значение или цель программной конструкции.

Эти функции могут быть реализованы по-разному. В MOO отражение является естественной частью повседневной идиомы программирования. Когда вызываются глаголы (методы), различные переменные, такие как verb (имя вызываемого глагола) и this (объект, для которого вызывается глагол), заполняются для определения контекста вызова. Безопасность обычно управляется программным доступом к стеку вызывающих: поскольку callers () - это список методов, с помощью которых в конечном итоге был вызван текущий глагол, выполнение тестов на callers () [0] (команда, вызванная исходным пользователем) позволяет глагол, чтобы защитить себя от несанкционированного использования.

Скомпилированные языки полагаются на свою систему времени выполнения, чтобы предоставить информацию об исходном коде. Скомпилированный исполняемый файл Objective-C, например, записывает имена всех методов в блоке исполняемого файла, предоставляя таблицу, чтобы сопоставить их с базовыми методами (или селекторами для этих методов), скомпилированными в программу. В скомпилированном языке, который поддерживает создание функций во время выполнения, например Common Lisp, среда выполнения должна включать компилятор или интерпретатор.

Отражение может быть реализовано для языков без встроенного отражения с помощью системы преобразования программ для определения автоматических изменений исходного кода.

Соображения безопасности

Отражение может позволить пользователю создавать неожиданные пути потока управления через приложение, потенциально обходя меры безопасности. Это может быть использовано злоумышленниками. Исторические уязвимости в Java, вызванные небезопасным отражением, позволили коду, полученному с потенциально ненадежных удаленных машин, вырваться из механизма безопасности изолированной программной среды Java. Крупномасштабное исследование 120 уязвимостей Java, проведенное в 2013 году, показало, что небезопасное отражение является наиболее распространенной уязвимостью в Java, хотя и не наиболее часто используемой.

Примеры

Следующие фрагменты кода создает экземпляр foo из класса Foo и вызывать его метод PrintHello. Для каждого языка программирования показаны обычные и основанные на отражении последовательности вызовов.

C #

Ниже приведен пример на C # :

// Without reflection Foo foo = new Foo(); foo.PrintHello(); // With reflection Object foo = Activator.CreateInstance("complete.classpath.and.Foo"); MethodInfo method = foo.GetType().GetMethod("PrintHello"); method.Invoke(foo, null);

Delphi / Object Pascal

В этом примере Delphi / Object Pascal предполагается, что класс TFoo объявлен в модуле с именем Unit1:

uses RTTI, Unit1; procedure WithoutReflection; var Foo: TFoo; begin Foo:= TFoo.Create; try Foo.Hello; finally Foo.Free; end; end; procedure WithReflection; var RttiContext: TRttiContext; RttiType: TRttiInstanceType; Foo: TObject; begin RttiType:= RttiContext.FindType('Unit1.TFoo') as TRttiInstanceType; Foo:= RttiType.GetMethod('Create').Invoke(RttiType.MetaclassType, []).AsObject; try RttiType.GetMethod('Hello').Invoke(Foo, []); finally Foo.Free; end; end;

eC

Ниже приведен пример в eC :

// Without reflection Foo foo { }; foo.hello(); // With reflection Class fooClass = eSystem_FindClass(__thisModule, "Foo"); Instance foo = eInstance_New(fooClass); Method m = eClass_FindMethod(fooClass, "hello", fooClass.module); ((void (*)())(void *)m.function)(foo);

Идти

Ниже приведен пример на Go :

import "reflect" // Without reflection f:= Foo{} f.Hello() // With reflection fT:= reflect.TypeOf(Foo{}) fV:= reflect.New(fT) m:= fV.MethodByName("Hello") if m.IsValid() { m.Call(nil) }

Джава

Ниже приведен пример на Java :

import java.lang.reflect.Method; // Without reflection Foo foo = new Foo(); foo.hello(); // With reflection try { Object foo = Foo.class.newInstance(); Method m = foo.getClass().getDeclaredMethod("hello", new Classlt;?gt;[0]); m.invoke(foo); } catch (ReflectiveOperationException ignored) {}

JavaScript

Ниже приведен пример на JavaScript :

// Without reflection const foo = new Foo() foo.hello() // With reflection const foo = Reflect.construct(Foo) const hello = Reflect.get(foo, 'hello') Reflect.apply(hello, foo, []) // With eval eval('new Foo().hello()')

Юлия

Ниже приведен пример на Julia (язык программирования) :

juliagt; struct Point x::Int y end # Inspection with reflection juliagt; fieldnames(Point) (:x,:y) juliagt; fieldtypes(Point) (Int64, Any) juliagt; p = Point(3,4) # Access with reflection juliagt; getfield(p,:x) 3

Цель-C

Ниже приведен пример в Objective-C, подразумевающий, что используется среда OpenStep или Foundation Kit :

// Foo class. @interface Foo : NSObject - (void)hello; @end // Sending "hello" to a Foo instance without reflection. Foo *obj = [[Foo alloc] init]; [obj hello]; // Sending "hello" to a Foo instance with reflection. id obj = [[NSClassFromString(@"Foo") alloc] init]; [obj performSelector: @selector(hello)];

Perl

Ниже приведен пример на Perl :

# Without reflection my $foo = Foo-gt;new; $foo-gt;hello; # or Foo-gt;new-gt;hello; # With reflection my $class = "Foo" my $constructor = "new"; my $method = "hello"; my $f = $class-gt;$constructor; $f-gt;$method; # or $class-gt;$constructor-gt;$method; # with eval eval "new Foo-gt;hello;";

PHP

Ниже приведен пример на PHP :

// Without reflection $foo = new Foo(); $foo-gt;hello(); // With reflection, using Reflections API $reflector = new ReflectionClass('Foo'); $foo = $reflector-gt;newInstance(); $hello = $reflector-gt;getMethod('hello'); $hello-gt;invoke($foo);

Python

Ниже приведен пример на Python :

# Without reflection obj = Foo() obj.hello() # With reflection obj = globals()["Foo"]() getattr(obj, "hello")() # With eval eval("Foo().hello()")

р

Ниже приведен пример на R :

# Without reflection, assuming foo() returns an S3-type object that has method "hello" obj lt;- foo() hello(obj) # With reflection class_name lt;- "foo" generic_having_foo_method lt;- "hello" obj lt;- do.call(class_name, list()) do.call(generic_having_foo_method, alist(obj))

Рубин

Ниже приведен пример на Ruby :

# Without reflection obj = Foo.new obj.hello # With reflection class_name = "Foo" method_name =:hello obj = Object.const_get(class_name).new obj.send method_name # With eval eval "Foo.new.hello"

Xojo

Ниже приведен пример использования Xojo :

' Without reflection Dim fooInstance As New Foo fooInstance.PrintHello ' With reflection Dim classInfo As Introspection.Typeinfo = GetTypeInfo(Foo) Dim constructors() As Introspection.ConstructorInfo = classInfo.GetConstructors Dim fooInstance As Foo = constructors(0).Invoke Dim methods() As Introspection.MethodInfo = classInfo.GetMethods For Each m As Introspection.MethodInfo In methods If m.Name = "PrintHello" Then m.Invoke(fooInstance) End If Next
Смотрите также
использованная литература

Цитаты

Источники

дальнейшее чтение
  • Ира Р. Форман и Нейт Форман, Отражение Java в действии (2005), ISBN   1-932394-18-4
  • Ира Р. Форман и Скотт Данфорт, Использование метаклассов в работе (1999), ISBN   0-201-43305-2
внешние ссылки
Последняя правка сделана 2023-04-16 02:18:14
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте