Refleksija (programiranje)

U informatici, refleksija je sposobnost nekog računarskog programa za ispitivanje (vidi tip introspekcije) i izmenu svoje strukture i ponašanja (konkretno vrednosti, meta-podatke, osobine i funkcije) u rantajmu.[1]

Istorijska pozadina

uredi

Najraniji računari su programirani na maternjem asembler jeziku, koji su bili po sebi odražavani kao ova originalna arhitektura koja može da se programira definisanjem instrukcija kao i korišćenjem podataka samo-modifikujućeg koda. Kao programiranje se preselilo u jezike visokog nivoa, kao što je C, ovo odražava sposobnost nestalu (van malvera) do programskih jezika sa odrazom ugrađenim u njihove tipove sistema pojava.

Brajan Kantvel Smitova 1982 doktorska disertacija[2][3] uvela je pojam računarske refleksije u programskim jezicima, kao i pojam meta-kružni prevodilac kao komponenta 3-Lisp.

Primene

uredi

Refleksija može da se koristi za posmatranje i dopunavanje izvršavanje programa na rantajmu. Refleksija orijentisana program komponenta može pratiti izvršenje kućišta koda i može se modifikovati prema željenom cilju u vezi sa tim kućištem. Ovo se obično postiže dinamičkom dodelom programskog koda u rantajmu.

U objektno orijentisanim programskim jezicima kao što su Java, refleksija omogućava pregled klasa, interfejsa, polja i metoda u toku rada ne znajući imena interfejsa, polja, metoda kompilacije. Ona takođe omogućava primernu novih objekata i pozivanje metoda.

Refleksija se takođe može koristiti za adaptiranje datog programa u različitim situacijama dinamike. Na primer, razmislite aplikaciju koja koristi dve različite klase X i Y naizmenično da obavljaju slične operacije. Bez refleksije orijentisanog programiranja, aplikacija može biti teško kodirana da pozove metod imena klaseX i klase Y. Međutim, koristeći refleksija orijentisanu paradigmu programiranja, aplikacija može biti dizajnirana i napisana da iskoristi refleksiju u cilju izazivanja metoda u klasama X i Y bez hard-kodiranja imena metoda. Refleksija-orijentisano programiranje skoro uvek zahteva dodatno znanje, okvir, relaciono mapiranje, a objekat relevantnost kako bi se iskoristio više generičko izvršenje koda.

Refleksija se često koristi kao deo testiranja softvera, kao što je za stvaranje Rantajma/primena probnih objekata.

Refleksija je takođe ključna strategija za metaprogramiranja.

U nekim objektno-orijentisanim programskim jezicima, kao što su C# i Java, refleksija može da se upotrebi da obori član pristupačnog pravila. Na primer, refleksija omogućava da promenite vrednost polja sa oznakom "privatno" u nezavisnu klasu biblioteke.

Implementacija

uredi

Jezik za podršku refleksije obezbeđuje veliki broj funkcija koje su dostupne na rantajmu koje bi inače bilo teško postići u jeziku nižeg nivoa. Neke od ovih funkcija su moguće do:

  • Otkrijte i modifikuje izvorni kod konstrukcija (kao što je kod blokova, klasa, metoda, protokola, itd) kao objekti prve klase na rantajmu.
  • Pretvaranje stringa koji odgovara simboličkom imenu klase ili funkcije u odnosu na ili upućivanje na te klase ili funkcije.
  • Procenite string kao da je izjava izvornog koda u rantajmu.
  • Kreirajte novi tumač za jezik bajtoka da da novi smisao ili cilj za programiranje konstrukta.

Ove karakteristike mogu se realizovati na različite načine. U MOO-u, refleksija predstavlja prirodan deo svakodnevnog programiranja idioma. Kada se zovu glagoli (metode), razne varijable kao što je glagol (ime glagola koji se zove) i ovo (predmet na koji se naziva glagol) su naseljeni da daju kontekst poziva. Bezbednost obično upravlja pristupom sagovorničkim štos programno: Kako je kod sagovornika () spisak načina na koji se trenutni glagol na kraju zovu, izvođenje testova sagovornika ()[1] (komande pozivaju originalnog korisnika) omogućava da se glagol zaštiti od neovlašćenog korišćenja.

Sastav jezika se oslanja na svoj rantajm sistem da pruži informacije o izvornom kodu. Sastav Objective-C izvršenja, na primer, beleži imena svih metoda u blok izvršenju, obezbeđujući sto da odgovara onim sa osnovnim metodama (ili selektore za ove metode) sastava u programu. U sastav jezika koji podržava rantajm stvaranje funkcija, kao što je Common Lisp, rantajm okruženje mora da sadrži kompajler ili prevodioca.

Refleksija se može realizovati za jezike koji nemaju ugrađene refleksije objekata pomoću programa transformacije sistema da definišu automatske promene izvornog koda.

Primeri

uredi

Kod sledeće kod komadići kreiraju instancu foo klase Foo, i pozivaju metodu hello. Za svaki programski jezik, normala i refleksija na bazi sekvence poziva se prikazuje.

U nastavku je primer u eC-u:

// без рефлексије
Foo foo { };
foo.hello();

// са рефлексијом
Class fooClass = eSystem_FindClass(__thisModule, "Foo");
Instance foo = eInstance_New(fooClass);
Method m = eClass_FindMethod(fooClass, "hello", fooClass.module);
((void (*)())(void *)m.function)(foo);

ECMAScript

uredi

U nastavku je primer u ECMAScript-u, i stoga važi i za Javaskript i ActionScript:

// без рефлексије
new Foo.hello()

// са рефлексијом

// под претпоставком да Foo борави у овде
new this['Foo']['hello']()

// или без претпоставке
new (eval('Foo'))['hello']()

// или једноставно
eval('new Foo.hello()')

U nastavku je primer u Javi:

// без рефлексије
Foo foo = new Foo();
foo.hello();

// са рефлексијом
Object foo = Class.forName("complete.classpath.and.Foo").newInstance();
// Алтернативно: Објекат foo = Foo.class.newInstance();
Method m = foo.getClass().getDeclaredMethod("hello", new Class<?>[0]);
m.invoke(foo);

Objective-C

uredi

Sledeći primer u Objective-C-u implicira OpenStep ili se koristi fondacija Kit okvir:

// Foo класа.
@interface Foo : NSObject
- (void)hello;
@end

// Слање "здраво" на пример Foo без рефлексије.
Foo *obj = [[Foo alloc] init];
[obj hello];

// Слање "здраво" на пример Фоо са рефлексијом.
id obj = [[NSClassFromString(@"Foo") alloc] init];
[obj performSelector: @selector(hello)];

Delfi

uredi

Ovaj Delfi primer pretpostavlja da TFoo klasa je deklarisana u jedinici pod nazivom Jedinica 1:

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;

Ovo je značajan primer, jer Delfi je bez menadžera, potpuno prirodno sastavljen jezik, za razliku od većine drugih jezika koji podržavaju razmišljanje. Njegova arhitektura jezika nasleđuje od snažnog-otkucanog Paskala, ali sa značajnim uticajem od SmallTalk-a. Uporedite sa ostalim primerima ovde, od kojih su mnogi dinamični ili skripte jezici kao što su Perl, Pajton ili PHP ili jezici sa rantajma kao Java ili C#.

U nastavku je primer u Perl-u:

# без рефлексије
my $foo = Foo->new;
$foo->hello;

# или
Foo->new->hello;

# са рефлексијом
my $class = "Foo"
my $constructor = "new";
my $method = "hello";

my $f = $class->$constructor;
$f->$method;

# или
$class->$constructor->$method;

# са eval-ом
eval "new Foo->hello;";

U nastavku je primer u PHP-u:

// без рефлексије
$foo = new Foo();
$foo->hello();

// са рефлексијом
$reflector = new ReflectionClass('Foo');
$foo = $reflector->newInstance();
$hello = $reflector->getMethod('hello');
$hello->invoke($foo);

// коришћење повратних позива
$foo = new Foo();
call_user_func(array($foo, 'hello'));

// коришћењем променљиве варијабле синтаксе
$className = 'Foo';
$foo = new $className();
$method = 'hello';
$foo->$method();

Pajton

uredi

U nastavku je primer u Pajtonu:

# без рефлексије
obj = Foo()
obj.hello()

# са рефлексијом
class_name = "Foo"
method = "hello"
obj = globals()[class_name]()
getattr(obj, method)()

# са eval-ом
eval("Foo().hello()")

U nastavku je primer u R-u:

# Без рефлексије, под претпоставком да foo () враћа С3-тип објекат који има методу "здраво"
obj <- foo()
hello(obj)

# са рефлексијом
the.class <- "foo"
the.method <- "hello"
obj <- do.call(the.class, list())
do.call(the.method, alist(obj))

U nastavku je primer u Rubiju:

# без рефлексије
obj = Foo.new
obj.hello

# са рефлексијом
class_name = "Foo"
method = :hello
obj = Object.const_get(class_name).new
obj.send method

# са eval-ом
eval "Foo.new.hello"

Vidi još

uredi
  • Tip introspekcija
  • Samo-modifikujući kod
  • Samo-domaćinski
  • Paradigme programiranja
  • Lista reflektujućih programskih jezika i platformi
  • Ogledalo (programiranje)

Reference

uredi

Literatura

uredi

Spoljašnje veze

uredi