2011-08-25 23 views
10

Tôi đang tạo một lớp kỳ lạ, nơi tôi muốn bắt mọi phương thức được gửi đến một đối tượng của lớp. Tôi có thể đạt được hầu hết những gì tôi muốn với method_missing, ví dụ:Ruby: Bắt tất cả các phương thức được gửi đến một đối tượng

class MyClass 
    def method_missing m, *args 
     # do stuff 
    end 
end 

Vấn đề là tất cả các phương pháp thể hiện mà MyClass kế thừa từ Đối tượng. Tôi có thể đi qua từng phương pháp từng người một và định nghĩa lại chúng, nhưng tôi đã hy vọng một cách tiếp cận linh hoạt hơn. Tất cả các phương thức lập trình meta tôi đã thử đã phàn nàn với một NameError khi tôi cố gắng chạm vào các phương thức instance đó.

Trả lời

11

Như đã đề cập trong các ý kiến ​​và câu trả lời từ @DanCheail, nếu bạn đang sử dụng ruby ​​1.9+, bạn nên sử dụng BasicObject thay vì phương pháp không xác định của Object. Tại thời điểm sử dụng bài viết này của 1.8.x vẫn còn khá phổ biến, mặc dù 1.9 đã được phát hành trong một thời gian.


Hơn là cố gắng "định nghĩa lại" bất cứ điều gì, bạn có thể quấn đối tượng của bạn trong một blanked (đối với hầu hết các phần) đối tượng proxy, một cái gì đó như:

class MyProxy 
    instance_methods.each do |meth| 
    # skipping undef of methods that "may cause serious problems" 
    undef_method(meth) if meth !~ /^(__|object_id)/ 
    end 

    def initialize(object) 
    @object = object 
    end  

    def method_missing(*args) 
    # do stuff 
    p args 
    # ... 
    @object.send(*args) 
    end 
end 

MyProxy.new(MyClass.new).whatever 
+0

Đó chính xác là những gì tôi đang tìm kiếm! – Max

+0

Tốt hơn nhiều khi sử dụng BasicObject, vì nó hoàn thành cùng một điều và an toàn hơn nhiều. – Max

+0

Lưu ý. Khi câu trả lời này được đăng 1.8 vẫn còn khá phổ biến trong các kịch bản sản xuất, và như vậy 'BasicObject' vẫn chưa tồn tại. – numbers1311407

5

Nếu bạn đang sử dụng của Ruby 1.9, bạn có thể có kế thừa lớp học của bạn từ BasicObject để có được một slate sạch để làm việc từ:

http://ruby-doc.org/core-1.9/classes/BasicObject.html

+0

Đó là loại điều tôi đang tìm kiếm, nhưng một nỗ lực tầm thường mang lại cho tôi mức độ 'SystemStackError: stack quá sâu' khi xác định' method_missing'. Hm ... – Max

+2

Bạn đang làm gì bên trong 'method_missing'? Nếu bạn đã làm một cái gì đó như 'đặt * args' bạn sẽ nhận được một vòng lặp' method_missing' vô tận. Nếu bạn cần một phương thức 'Kernel', bạn phải gọi' :: Kernel.puts', v.v. – numbers1311407

1

Nếu bạn đang sử dụng Ruby 1,8 bạn có thể xem xét sử dụng đá quý blankslate.

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