Reflection (תכנות)במדעי המחשב, reflection (ריפלקשן; מילולית מאנגלית: השתקפות או התבוננות) היא היכולת של תוכנת מחשב לבחון אובייקטים או לשנות את התנהגותם בזמן ריצה. בחינת האובייקטים מבוצעת באמצעות תהליך הנקרא type introspection - "הסתכלות פנימה על טיפוסים", ושינוי ההתנהגות של אובייקטים כוללת את היכולת לשנות ערכים, metadata, תכונות (properties) ופונקציות. השימוש הנפוץ ביותר ב-reflection הוא בשפות עילית הרצות על גבי מכונה וירטואלית, כדוגמת Smalltalk. כמו כן השימוש ב-reflection נפוץ בשפות תסריט ובשפות בעלות טיפוסיות סטטית כגון: ML, Java, ו-Haskell. לשפות תכנות התומכות ב-reflection קוראים "שפות רפלקטיביות" (reflective languages). לתכנות הכולל שימוש ב-reflection קוראים "תכנות מונחה-reflection-oriented programming) "reflection). רקע היסטוריהתכנות של מחשבים מוקדמים בוצע בשפת הסף הטבעית שלהם. שפות סף כאלה הן רפלקטיביות מטבען, מכיוון שהן פועלות על ידי הגדרת ההוראות בצורה של נתונים. פונקציונליות רפלקטיבית כגון שינוי ההוראות או ניתוח שלהן הייתה דבר שבשגרה. כאשר התכנות התקדם לשפות תכנות עיליות יותר כדוגמת שפת C, השימוש ב-reflection נעלם, עד שהופיעו שפות תכנות שמערכת הטיפוסים שלהן כוללת תמיכה ב-reflection. שימושיםניתן להשתמש ב-reflection כדי לבחון את ביצוע התוכנית ולהשפיע עליה בזמן ריצה. רכיב בתוכנה מונחית-reflection יכול לפקח אחר הביצוע של יחידת קוד, ולשנות את עצמו בהתאם למטרה שרוצים להשיג בהקשר ליחידת קוד זו. בדרך כלל זה נעשה על ידי הקצאת קוד בזמן ריצה. בשפות תכנות מונחות-עצמים כמו Java, שימוש ב-reflection מאפשר בדיקה בזמן ריצה של מחלקות, ממשקים, שדות ומתודות, מבלי לדעת את השמות שלהם בזמן הידור. כמו כן זה מאפשר יצירת מופעים חדשים של אובייקטים וקריאה למתודות. בנוסף לכך, ניתן להשתמש ב-reflection על מנת לסגל תוכניות למצבים שונים בצורה דינאמית. לדוגמה, נחשוב על יישום המשתמש לסירוגין בשתי מחלקות שונות, על מנת לנצל את היתרונות שבכתיבת קוד גנרי יותר באמצעות תכנות מונחה-reflection, כמעט תמיד נדרשות מומחיות ותשתיות תוכנה נוספות. מידת השימוש ב-reflection קובעת עד כמה ניתן יהיה להימנע משימוש ב-hard coding (קידוד קשיח). לעיתים קרובות משתמשים ב-reflection בבדיקות תוכנה, כאשר רוצים ליצור מופעים של "אובייקטי דמה" (mock objects) בזמן ריצה. כמו כן, reflection היא האסטרטגיה הראשית ב-metaprogramming – כתיבת תוכנות מחשב שכותבות או משנות תוכנות אחרות. מימוששפת תכנות הכוללת תמיכה ב-reflection, מספקת מספר שירותים ייעודיים הזמינים בזמן ריצה, שאחרת היו קשים מאוד למימוש בשפה שהיא low-level יותר. בין היתר, שירותים אלו מאפשרים:
שירותים אלה ניתנים למימוש בדרכים שונות. שפות העוברות הידור מסתמכות על מערכת סביבת ההרצה (runtime) שלהן כדי לקבל מידע אודות קוד המקור. לדוגמה, קובץ הרצה מהודר בשפת Objective-C, שומר את שמות כל המתודות בבלוק בתוך הקובץ, ובכך מספק טבלה להתאמה בין שמות המתודות למתודות עצמן בתוכנית המהודרת. בשפה מהודרת התומכת ביצירת פונקציות בזמן ריצה, כדוגמת Common Lisp, סביבת ההרצה חייבת לכלול מהדר או מפרש. כמו כן, ניתן לממש reflection גם בשפות שאינן כוללות מנגנונים מובנים לתמיכה ב-reflection, על ידי שימוש במערכת ל-program transformation, כדי להגדיר שינויים אוטומטיים בקוד המקור. דוגמאותקטעי הקוד הבאים יוצרים מופע // Using Java package: java.lang.reflect
// Without reflection
new Foo().hello();
// With reflection
Class<?> clazz = Class.forName("Foo");
clazz.getMethod("hello").invoke(clazz.newInstance());
// 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()')
// without reflection
$foo = new Foo();
$foo->hello();
// with reflection
$reflector = new ReflectionClass('Foo');
$foo = $reflector->newInstance();
$hello = $reflector->getMethod('hello');
$hello->invoke($foo);
// using callback
$foo = new Foo();
call_user_func(array($foo, 'hello'));
// using variable variables syntax
$className = 'Foo';
$foo = new $className();
$method = 'hello';
$foo->$method();
# without reflection
obj = Foo.new
obj.hello
# with reflection
class_name = "Foo"
method = :hello
obj = Kernel.const_get(class_name).new
obj.send method
// Foo class
@interface Foo : NSObject
- (void)hello;
//...
@end
// without reflection
Foo *obj = [[Foo alloc] init];
[obj hello];
// with reflection in OPENSTEP, loading class and call method using variables.
NSString *className = @"Foo";
SEL selector = @selector(hello);
id obj = [[NSClassFromString(className) alloc] init];
[obj performSelector:selector]; // This will emit an warning when compiling with Objective-C ARC.
ראו גםקישורים חיצוניים
|