برنامهنویسی پژواکی
در علوم رایانه، پژواک (به انگلیسی: Reflection) توانایی یک پردازه برای آزمون، خوداندیشی، و اصلاح «ساختار» و «رفتار» داخلی خودش میباشد.[۱]
کاربردها
ویرایش- پژواک به برنامهنویس کمک میکند تا کتابخانههای نرمافزاری همگانی بسازد که هدف آن میتواند: نمایش داده، پردازش قالبهای مختلف داده، انجام سریال سازی، یا انجام بازگشت سریال سازی داده برای ارتباطات، یا بستهبندی یا جداسازی از بسته برای داده برای ارتباطات ظرف دهی شده یا ارتباطات انفجاری باشد.[۲]
- استفاده از پژواک به زبان کمک میکند تا برای کدهای «مبتنی-بر-شبکه» مناسب باشد.[۲]
- از پژواک برای مشاهده و اصلاح اجرای برنامه، در «زمان اجرا» استفاده میشود.[۲]
- در زبانهای برنامهنویسی شی گرا مثل جاوا، پژواک امکان بازرسی کلاسها، واسطها، فیلدها، و متدها را در زمان اجرا میدهد، حتی اگر نام واسطها، فیلدها، و متدها در زمان کامپایل را ندانیم. این موضوع امکان نمونه برداری از اشیای جدید و فراخوانی متدها را میدهد.[۲]
- از پژواک معمولاً به عنوان بخشی از آزمون نرمافزار، استفاده میشود، مثلاً برای ساخت/نمونه برداری از اشیای ساختگی.[۲]
- پژواک یک استراتژی کلیدی برای فرا برنامهنویسی است.[۲]
- در بعضی از زبانهای برنامهنویسی شی گرا، مثل سی شارپ، و جاوا، از پژواک میتوان در انتقال قواعد دسترسی عضو استفاده کرد.[۲]
استفادهٔ مؤثر از پژواک، تقریباً همیشه نیاز به یک برنامه دارد: یک چهارچوب طراحی، توصیف کد دهی، کتابخانه شیی، یا تناظر یک پایگاه داده یا ارتباطات موجودیت.[۲]
پیادهسازی
ویرایشیک زبان پشتیبانی کننده از پژواک، ویژگیهایی را تدارک میبیند که در «زمان اجرا» استفاده میشوند، اگر این ویژگیها وجود نداشته باشد، پیادهسازی پژواک در زبانهای سطح پایین بسیار سخت است.[۲]
بعضی از این ویژگیها، در ادامه ذکر میشوند، توانایی برای:
- تشخیص و اصلاح ساختمانهای کد منبع (مثل بلاک کد، کلاسها، متدها، پروتکلها و غیره) به عنوان اشیای کلاس سطح اول، در زمان اجرا.
- تبدیل یک رشته که با نام نمادین یک کلاس یا تابع منطبق است به یک ارجاع (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
ویرایشدر ادامه یک مثال به زبان 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)];
Perl
ویرایشدر ادامه یک مثال در زبان پرل آمدهاست:
# 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
ویرایشدر ادامه یک مثال به زبان 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
ویرایشدر ادامه یک مثال به زبان 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))
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
منابع
ویرایش- ↑ 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
- ↑ ۲٫۰۰ ۲٫۰۱ ۲٫۰۲ ۲٫۰۳ ۲٫۰۴ ۲٫۰۵ ۲٫۰۶ ۲٫۰۷ ۲٫۰۸ ۲٫۰۹ ۲٫۱۰ "Reflection (computer programming)". Wikipedia (به انگلیسی). 2019-12-30.