Reflection (khoa học máy tính)

Bách khoa toàn thư mở Wikipedia
Bước tới: menu, tìm kiếm

Trong khoa học máy tính, khả năng phục hồi (hay reflection) được hiểu là khả năng quan sát và tự chỉnh sửa cấu trúc ở mức cao của một của một chương trình (máy tính). Thông thường, reflection dùng để chỉ khả năng phục hồi động hay khả năng phục hồi trong thời gian thực thi (runtime reflection), mặc dù vậy, một số ngôn ngữ lập trình hỗ trợ phục hồi tĩnh hay phục hồi tại thời gian biên dịch (compile time reflection). Khả năng này thường có trong các ngôn ngữ lập trình cấp cao chạy ở máy ảo như Smalltalk, và ít phổ biến ở các ngôn ngữ lập trình cấp thấp như C.

Mẫu hình lập trình kiểu reflection được gọi là lập trình có tính chất phục hồi.

Khi mã nguồn của một chương trình được biên dịch, các thông tin về cấu trúc của chương trình (như struct, tên biến, tên phương thức, tên class...) thường bị mất đi khi đã chuyển thành mã cấp thấp (thường là mã nhị phân). Nếu một hệ thống có hỗ trợ phục hồi thì thông tin cấu trúc sẽ được bảo toàn dưới dạng siêu dữ liệu cùng với mã được sinh ra.

Tùy vào cách hiện thực, đoạn mã với khả năng phục hồi thường chạy chậm hơn khi không có nó.

Trong các ngôn ngữ mà không có sự khác biệt giữa thời gian thi hànhthời gian dịch (ví dụ: Lisp và các biến thể của nó), thì không có sự khác biệt giữa biên dịch và thông dịch của mã và sự phục hồi.

Các hiện thực[sửa | sửa mã nguồn]

Một ngôn ngữ khi hỗ trợ khả năng phục hồi thường cung cấp một số tính năng, tại thời gian chạy, mà có thể là khó hay không thể thực hiện được đối với các ngôn ngữ cấp thấp. Một số tính năng đó là:

  • Xác định và chỉnh sửa các lệnh thực thi của mã nguồn (như các khối mã lệnh, lớp, phương pháp, giao thức,... vân vân.).
  • Chuyển đổi một chuỗi giống với một tên (symbolic name) của một lớp hay hàm thành một tham chiếu đến lớp hay hàm đó và có thể gọi chúng.
  • Kiểm tra, tại thời gian chạy, một chuỗi xem thử nó có thể là một câu lệnh đúng hay không. Nếu đúng, ta có thể gọi nó để thực thi.

Có nhiều cách để hiện thức các tính năng này. Ngôn ngữ thông dịch, như RubyPHP, là lí tưởng cho reflection, vì mã nguồn của chúng là không bao giờ mất trong quá trình đổi thành mã máy; bộ thông dịch luôn có mã nguồn của chương trình.

Ngôn ngữ theo hướng biên dịch dựa vào hệ thống thời gian chạy để cung cấp thông tin về mã nguồn. Ví dụ, một mã thực thi của ngôn ngữ Objective-C lưu tên của mọi phương thức vào trong một khối thực thi, cung cấp một bảng để ánh xạ những tên này với các phương thức bên dưới (hay selector cho những phương thức này), được biên dịch trong chương trình. Trong ngôn ngữ theo hướng biên dịch mà có hỗ trợ việc tạo động các hàm—như Common Lisp—thì môi trường chạy phải kèm theo trình dịch..

Các ngôn ngữ lập trình và nền tảng hỗ trợ reflection[sửa | sửa mã nguồn]

Các nền tảng hỗ trợ reflection đã được biết bao gồm các ngôn ngữ định kiểu động (ví dụ, Objective-C, Ruby, Smalltalk), các ngôn ngữ văn lệnh (ví dụ, Perl, PHP, Python, Ruby, VBScript, JavaScript); và hệ thống Maude của việc viết lại logic.

Ví dụ[sửa | sửa mã nguồn]

Đoạn mã sau là ví dụ viết bằng Java.

// Không dùng reflection
Foo foo = new Foo ();
foo.hello ();
// Dùng reflection
Class cl = Class.forName ("Foo");
Method method = cl.getMethod ("hello", null);
method.invoke (cl.newInstance (), null);

Cả 2 đoạn code trên đều tạo ra một thực thể của lớp 'Foo' và gọi phương thức 'hello' của nó. Sự khác biệt là, trong đoạn đầu, các tên của lớp và phương thức thì được viết kiểu "mã cứng" (hard-coded); và nó không thể dùng tên của lớp khác. Trong đoạn mã sau, tên của lớp và phương thức có thể dễ dàng thay đổi vào thời gian thực thi. Một sự khác biệt lớn nữa là đoạn mã thứ nhì này khó hiểu hơn.

(Tham khảo java.lang.reflect.)

Đây là ví dụ tương tự với Perl:

# Không dùng reflection
Foo->new->hello;
# Dùng reflection
my $class = "Foo";
my $method = "hello";
$class->new->$method;

Tham khảo thêm[sửa | sửa mã nguồn]

Liên kết ngoài[sửa | sửa mã nguồn]