2013-03-04 19 views
5

Tôi đang cố gắng sử dụng các phương pháp phản xạ trong Ruby, và chạy vào một hành vi mà tôi tìm thấy thực sự surpising.Tại sao lại là Module.methods() và respond_to? hoạt động khác nhau trong irb hơn trong kịch bản?

Các ví dụ sau dường như làm việc khác nhau trong IRB và khi được gọi là một kịch bản ruby:

Ví dụ 1:

def myfun; end 
p respond_to?(:myfun) 

Trong IRB, điều này nói 'true', Trong kịch bản: 'false' .

Ví dụ 2:

ml = methods 
def myfun; end 
p methods - ml 

Trong IRB, điều này nói [: myfun]. Trong tập lệnh: [].

Tôi thấy điều này dưới 1,8, 1,9 MRI, JRuby 1.5.6, vv - vì vậy tôi cho rằng đây là điều bình thường.

Tại sao là sự khác biệt?

Tôi khá chắc chắn 'respond_to?' là cách để xem liệu một phương thức có sẵn không - tại sao lại không hoạt động trong trường hợp trên?

Trả lời

5

Chức năng này - phương pháp trên đối tượng "chính" - được định nghĩa là tư nhân trong kịch bản ruby. Bạn có thể kiểm tra điều này một cách dễ dàng:

ml = private_methods 
def myfun; end 
p private_methods - ml #=> [:myfun] 
p respond_to?(:myfun, true) #=> true 

Nếu bạn gọi nó một cách rõ ràng về tự bạn sẽ nhận được một lỗi:

self.myfun 
# NoMethodError: private method ‘myfun’ called for main:Object 

Mặt khác, trong IRB phương pháp của bạn được định nghĩa là công cộng. Dưới mui xe nó trông giống như sau:

class Object 
    def irb_binding 
    # this is where your entered code is evaluated 
    def myfun; :ok; end # you can define methods in other methods 
    self.myfun # and they are public by default 
    end 
end 

p irb_binding # :ok 

IRB có thể dễ dàng đánh giá ở cấp cao nhất mà thay vào đó nó tạo ra một môi trường riêng biệt với phương pháp này để các biến địa phương không được chia sẻ:

require "irb" 
foo = :ok 
IRB.start 
#>> foo 
# NameError: undefined local variable or method `foo' for main:Object 

tôi phương pháp nghĩ là công khai chỉ là trùng hợp ngẫu nhiên do việc triển khai và không quan trọng lắm. Những phương thức này tạm thời.

+0

Rất tốt để biết - thật tuyệt vời Tôi đã không gặp phải điều này sau nhiều năm tiếp xúc với Ruby .. Có, tôi quan tâm đến lý do tại sao IRB công khai họ đang cố gắng thân thiện hơn? :) Tôi có thể thấy lý do tại sao bình thường họ là tư nhân - để tránh nhầm lẫn như "def f; kết thúc; lớp A; kết thúc; A.new.f", hoặc một cái gì đó như thế? – inger

+0

Tôi cũng rất ngạc nhiên khi biết điều này. –

+0

@Semyon Bạn có thể giải thích tại sao các phương thức 'irb' được công khai không? Và tại sao trong 'irb'' myfun' và 'self.myfun' lại đề cập đến cùng một phương thức? – codeit