2008-09-08 42 views
18

Gần đây tôi đã nói chuyện với một đồng nghiệp về C++ và than thở rằng không có cách nào để lấy một chuỗi có tên của một trường lớp và trích xuất trường bằng tên đó; nói cách khác, nó thiếu sự phản chiếu. Anh ấy đã cho tôi một cái nhìn bối rối và hỏi khi nào có ai cần phải làm một điều như vậy.Trường hợp sử dụng để phản ánh

Tắt đầu tôi không có câu trả lời hay cho anh ấy, ngoài "hey, tôi cần làm ngay bây giờ". Vì vậy, tôi ngồi xuống và đưa ra một danh sách một số điều tôi đã thực sự thực hiện với sự phản ánh bằng nhiều ngôn ngữ khác nhau. Thật không may, hầu hết các ví dụ của tôi đến từ lập trình web của tôi bằng Python và tôi hy vọng rằng những người ở đây sẽ có nhiều ví dụ hơn. Dưới đây là danh sách tôi đã đưa ra: "Hello World!"

  1. Cho một tập tin cấu hình với những đường nét như
    x =
    y = 5.0
    đặt động các trường của một số đối tượng config bằng giá trị trong tệp đó. (Đây là điều tôi ước tôi có thể làm trong C++, nhưng thực sự không thể làm được.)

  2. Khi sắp xếp danh sách các đối tượng, sắp xếp dựa trên thuộc tính tùy ý cho tên thuộc tính đó từ tệp cấu hình hoặc yêu cầu web.

  3. Khi viết phần mềm sử dụng giao thức mạng, phản ánh cho phép bạn gọi các phương thức dựa trên giá trị chuỗi từ giao thức đó. Ví dụ: tôi đã viết một bot IRC có thể dịch
    !some_command arg1 arg2
    vào một phương thức gọi actions.some_command(arg1, arg2) và in bất kỳ chức năng nào được trả về kênh IRC.

  4. Khi sử dụng hàm __getattr__ của Python (giống như method_missing trong Ruby/Smalltalk), tôi đã làm việc với một lớp có rất nhiều thống kê, chẳng hạn như late_total. Đối với mỗi thống kê, tôi muốn có thể thêm _percent để có được thống kê đó theo tỷ lệ phần trăm của tổng số thứ tôi đã đếm (ví dụ: stats.late_total_percent). Sự phản ánh làm điều này rất dễ dàng.

Vì vậy, bất kỳ ai ở đây có thể đưa ra ví dụ từ trải nghiệm lập trình của riêng họ khi phản ánh hữu ích không? Lần sau, một đồng nghiệp hỏi tôi tại sao tôi lại muốn "làm như thế" Tôi muốn chuẩn bị kỹ hơn.

Trả lời

14

tôi có thể liệt kê sử dụng sau đây để phản ánh:

  • Late binding
  • An (mã nội quan vì lý do an ninh)
  • Mã phân tích
  • động gõ (vịt gõ là không thể không phản ánh)
  • Lập trình meta metaprogramming

Một số tập quán thực tế của sự phản xạ từ kinh nghiệm cá nhân của tôi:

  • Phát triển hệ thống plugin dựa trên phản ánh
  • đã qua sử dụng khía cạnh định hướng mô hình lập trình
  • Thực hiện mã tĩnh phân tích
  • sử dụng khác nhau khuôn khổ Dependency Injection
  • ...

Phản ánh là điều tốt :)

2

Có rất nhiều lần bạn muốn tự động khởi tạo và làm việc với các đối tượng không biết loại cho đến khi thời gian chạy. Ví dụ với OR-mappers hoặc trong một kiến ​​trúc plugin. Mocking framework sử dụng nó, nếu bạn muốn viết một thư viện logging và tự động muốn kiểm tra kiểu và các thuộc tính của các ngoại lệ.

Nếu tôi nghĩ lâu hơn một chút, tôi có thể tìm ra nhiều ví dụ hơn.

1

Viết điều phối viên. Twisted sử dụng khả năng phản chiếu của python để gửi các cuộc gọi XML-RPC và SOAP. RMI sử dụng api phản chiếu của Java để gửi đi.

Phân tích dòng lệnh. Xây dựng một đối tượng cấu hình dựa trên các tham số dòng lệnh được truyền vào.

Khi viết các bài kiểm tra đơn vị, có thể hữu ích khi sử dụng sự phản chiếu, chủ yếu là tôi đã sử dụng điều này để bỏ qua bộ sửa đổi truy cập (Java).

1

Tôi đã sử dụng phản chiếu trong C# khi có một số phương pháp nội bộ hoặc riêng tư trong khung hoặc thư viện của bên thứ ba mà tôi muốn truy cập.

(Disclaimer:.. Nó không nhất thiết là một thực hành tốt nhất vì phương pháp riêng và nội bộ có thể được thay đổi trong các phiên bản sau Nhưng nó làm việc cho những gì tôi cần thiết)

1

Vâng, trong ngôn ngữ tĩnh đánh máy, bạn muốn muốn sử dụng sự phản chiếu bất cứ khi nào bạn cần làm một cái gì đó "năng động". Nó có ích cho các mục đích dụng cụ (quét các thành viên của một đối tượng). Trong Java nó được sử dụng trong JMX và proxy động khá một chút. Và có vô số trường hợp một lần mà nó thực sự là cách duy nhất để đi (khá nhiều bất cứ lúc nào bạn cần làm một cái gì đó trình biên dịch sẽ không cho phép bạn làm).

4

Tôi đã sử dụng phản ánh để có được thông tin cập nhật phương pháp cho trường hợp ngoại lệ, khai thác gỗ, vv

string src = MethodInfo.GetCurrentMethod().ToString(); 
string msg = "Big Mistake"; 
Exception newEx = new Exception(msg, ex); 
newEx.Source = src; 

thay vì

string src = "MyMethod"; 
string msg = "Big MistakeA"; 
Exception newEx = new Exception(msg, ex); 
newEx.Source = src; 

Nó chỉ là dễ dàng hơn cho copy/paste thừa kế và thế hệ mã.

+0

Chính xác "sao chép/dán thừa kế" là gì? Và bạn không có một dấu vết ngăn xếp trong ngoại lệ của bạn không? – Groo

+0

Trong trường hợp tôi sử dụng điều này, ngoại lệ cuối cùng đã được ghi vào một tệp văn bản và theo dõi ngăn xếp không được ghi lại. – jrcs3

+0

Không sử dụng phương pháp này trong mã sản xuất. Trong bản phát hành bản phát hành, ngăn xếp có thể và sẽ bị thu gọn do kết quả của chuỗi nội tuyến và chuỗi phương pháp (ví dụ: tối ưu hóa cuộc gọi đuôi). Nếu bạn đăng nhập một ngoại lệ, bạn có stacktrace anyway (không có lý do để thêm nguồn bằng tay). Sử dụng 'GetCurrentMethod' một cách thận trọng và trong quá trình gỡ lỗi chỉ được xây dựng. – Abel

3

Tôi đang ở trong tình huống hiện tại nơi tôi có luồng XML đến qua dây và tôi cần khởi tạo đối tượng Entity sẽ tự cư trú từ các phần tử trong luồng. Sẽ dễ sử dụng sự phản chiếu hơn để tìm ra đối tượng Entity nào có thể xử lý phần tử XML nào hơn là viết một câu lệnh điều kiện khổng lồ, duy trì cơn ác mộng. Rõ ràng là một sự phụ thuộc giữa lược đồ XML và cách tôi cấu trúc và đặt tên cho các đối tượng của mình, nhưng tôi kiểm soát cả hai vì vậy nó không phải là một vấn đề lớn.

2

Tôi thấy sự phản chiếu rất hữu ích nếu dữ liệu đầu vào (như xml) có cấu trúc phức tạp dễ dàng được ánh xạ tới các cá thể đối tượng hoặc tôi cần một loại quan hệ "là" giữa các cá thể.

Do sự phản chiếu tương đối dễ trong java, đôi khi tôi sử dụng nó cho dữ liệu đơn giản (bản đồ giá trị khóa), nơi tôi có một bộ khóa cố định nhỏ. Một mặt đơn giản để xác định xem một khóa có hợp lệ không (nếu lớp có setter setKey (String data)), mặt khác tôi có thể thay đổi kiểu dữ liệu đầu vào (textual) và ẩn phép chuyển đổi (ví dụ: cast đơn giản) để int trong getKey()), vì vậy phần còn lại của ứng dụng có thể dựa vào dữ liệu được nhập chính xác. Nếu kiểu của một số cặp khóa-giá trị thay đổi cho một đối tượng (ví dụ: int thành float), tôi chỉ phải thay đổi nó trong đối tượng dữ liệu và người dùng của nó nhưng không cần phải nhớ để kiểm tra trình phân tích cú pháp quá. Đây có thể không phải là một cách tiếp cận hợp lý, nếu hiệu suất là một vấn đề ...

1

Tôi thường sử dụng phản chiếu để gỡ lỗi. Sự phản xạ có thể hiển thị chính xác hơn và chính xác hơn các đối tượng trong hệ thống hơn là một loại các câu lệnh in. Trong nhiều ngôn ngữ có các hàm hạng nhất, bạn thậm chí có thể gọi các hàm của đối tượng mà không cần viết mã đặc biệt. Tuy nhiên, có một cách để làm những gì bạn muốn (ed). Sử dụng hashtable. Lưu trữ các trường được khóa với tên trường.

Nếu bạn thực sự muốn, bạn có thể tạo các chức năng Get/Set tiêu chuẩn hoặc tạo macro chạy nhanh. #define GetX() Get("X") loại điều.

Bạn thậm chí có thể thực hiện sự phản chiếu không hoàn hảo của riêng mình theo cách đó.

Đối với người dùng nâng cao, nếu bạn có thể biên dịch mã, có thể bật tính năng tạo đầu ra gỡ lỗi và sử dụng để thực hiện phản ánh.

Các vấn đề liên quan