برنامه‌نویسی پژواکی

در علوم رایانه، پژواک توانایی یک پردازه برای آزمون، خوداندیشی، و اصلاح «ساختار» و «رفتار» داخلی خودش می باشد.

در علوم رایانه، پژواک (به انگلیسی: Reflection) توانایی یک پردازه برای آزمون، خوداندیشی، و اصلاح «ساختار» و «رفتار» داخلی خودش می‌باشد.[۱]

کاربردها

ویرایش
  1. پژواک به برنامه‌نویس کمک می‌کند تا کتابخانه‌های نرم‌افزاری همگانی بسازد که هدف آن می‌تواند: نمایش داده، پردازش قالب‌های مختلف داده، انجام سریال سازی، یا انجام بازگشت سریال سازی داده برای ارتباطات، یا بسته‌بندی یا جداسازی از بسته برای داده برای ارتباطات ظرف دهی شده یا ارتباطات انفجاری باشد.[۲]
  2. استفاده از پژواک به زبان کمک می‌کند تا برای کدهای «مبتنی-بر-شبکه» مناسب باشد.[۲]
  3. از پژواک برای مشاهده و اصلاح اجرای برنامه، در «زمان اجرا» استفاده می‌شود.[۲]
  4. در زبان‌های برنامه‌نویسی شی گرا مثل جاوا، پژواک امکان بازرسی کلاس‌ها، واسط‌ها، فیلدها، و متدها را در زمان اجرا می‌دهد، حتی اگر نام واسط‌ها، فیلدها، و متدها در زمان کامپایل را ندانیم. این موضوع امکان نمونه برداری از اشیای جدید و فراخوانی متدها را می‌دهد.[۲]
  5. از پژواک معمولاً به عنوان بخشی از آزمون نرم‌افزار، استفاده می‌شود، مثلاً برای ساخت/نمونه برداری از اشیای ساختگی.[۲]
  6. پژواک یک استراتژی کلیدی برای فرا برنامه‌نویسی است.[۲]
  7. در بعضی از زبان‌های برنامه‌نویسی شی گرا، مثل سی شارپ، و جاوا، از پژواک می‌توان در انتقال قواعد دسترسی عضو استفاده کرد.[۲]

استفادهٔ مؤثر از پژواک، تقریباً همیشه نیاز به یک برنامه دارد: یک چهارچوب طراحی، توصیف کد دهی، کتابخانه شیی، یا تناظر یک پایگاه داده یا ارتباطات موجودیت.[۲]

پیاده‌سازی

ویرایش

یک زبان پشتیبانی کننده از پژواک، ویژگی‌هایی را تدارک می‌بیند که در «زمان اجرا» استفاده می‌شوند، اگر این ویژگی‌ها وجود نداشته باشد، پیاده‌سازی پژواک در زبان‌های سطح پایین بسیار سخت است.[۲]

بعضی از این ویژگی‌ها، در ادامه ذکر می‌شوند، توانایی برای:

  • تشخیص و اصلاح ساختمان‌های کد منبع (مثل بلاک کد، کلاس‌ها، متدها، پروتکل‌ها و غیره) به عنوان اشیای کلاس سطح اول، در زمان اجرا.
  • تبدیل یک رشته که با نام نمادین یک کلاس یا تابع منطبق است به یک ارجاع (reference) یا به فراخوانی (invocation) آن کلاس یا تابع.
  • یک رشته، را بتوان به صورت یک عبارت کد منبع در زمان اجرا ارزیابی کرد.
  • تولید یک مفسر جدید برای بایت‌کد یک زبان، که در این قابلیت، مقصود ایجاد یک معنی جدید یا هدف جدید برای یک ساختار برنامه‌نویسی می‌باشد.[۲]

مثال‌ها

ویرایش

قطعه کدهایی که در ادامه می‌آیند یک نمونه foo از کلاس Foo را می‌سازند، و متد PrintHello آن را فراخوانی می‌کنند. برای هر زبان برنامه‌نویسی، ترتیب صدا زدن نرمال و مبتنی بر پژواک نشان داده شده‌است.[۲]

سی شارپ

ویرایش

در ادامه یک مثال به زبان سی شارپ آمده‌است:

// 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);

این مثال دلفی فرض کرده‌است که یک کلاس 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 آمده‌است:

// 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);

ECMAScript

ویرایش

در ادامه یک مثال یه زبان ECMAScript آمده‌است، و بنابراین به JavaScript و ActionScript اعمال می‌شود:

// Without reflection
new Foo().hello()

// With reflection

// assuming that Foo resides in this
new this['Foo']()['hello']()

// or without assumption
new (eval('Foo'))()['hello']()

// or simply
eval('new Foo().hello()')

// Using ECMAScript 2015's new Reflect class:
Reflect.construct(Foo, [])['hello']()

در ادامه یک مثال به زبان 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)
}

در ادامه یک مثال به زبان جاوا آمده‌است:

import java.lang.reflect.Method;

// Without reflection
Foo foo = new Foo();
foo.hello();

// With reflection
try {
    // Alternatively: Object foo = Foo.class.newInstance();
    Object foo = Class.forName("complete.classpath.and.Foo").newInstance();

    Method m = foo.getClass().getDeclaredMethod("hello", new Class<?>[0]);
    m.invoke(foo);
} catch (Exception e) {
    // Catching ClassNotFoundException, NoSuchMethodException
    // InstantiationException, IllegalAccessException
}

Objective-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)];

در ادامه یک مثال در زبان پرل آمده‌است:

# Without reflection
my $foo = Foo->new;
$foo->hello;
# or
Foo->new->hello;
# With reflection
my $class = "Foo"
my $constructor = "new";
my $method = "hello";

my $f = $class->$constructor;
$f->$method;
# or
$class->$constructor->$method;
# with eval
eval "new Foo->hello;";

در ادامه یک مثال به زبان PHP آمده‌است:

// Without reflection
$foo = new Foo();
$foo->hello();

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

پایتون

ویرایش

در ادامه یک مثال در زبان پایتون آمده‌است:

# 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 <- foo()
hello(obj)
# With reflection
the.class <- "foo"
the.method <- "hello"
obj <- do.call(the.class, list())
do.call(the.method, alist(obj))

در ادامه یک مثال به زبان روبی آمده‌است:

# 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 آمده‌است:

' 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

منابع

ویرایش
  1. A Tutorial on Behavioral Reflection and its Implementation by Jacques Malenfant et al. (PDF), unknown, archived from the original (PDF) on 21 August 2017, retrieved 23 June 2019
  2. ۲٫۰۰ ۲٫۰۱ ۲٫۰۲ ۲٫۰۳ ۲٫۰۴ ۲٫۰۵ ۲٫۰۶ ۲٫۰۷ ۲٫۰۸ ۲٫۰۹ ۲٫۱۰ "Reflection (computer programming)". Wikipedia (به انگلیسی). 2019-12-30.