2012-01-01 27 views
5

Lấy cảm hứng từ điều này article, tôi đã chơi xung quanh với phương pháp gọi là phân cấp của Ruby và nhận thấy điều gì đó kỳ lạ.Phân cấp gọi phương thức Ruby

Given:

class B 
    def foo 
    "- Instance method defined by B" 
    end 

    def method_missing(method) 
    puts "- method_missing (#{method}) on b. Redirecting to b.foo\n" 
    foo 
    end 
end 

b = B.new 

def b.foo 
    "- Method defined directly on an instance of B\n" + super 
end 

def b.method_missing(method) 
    "- method_missing (#{method}) on b. Calling super\n" + super 
end 

puts "Calling 'bar' on b of type #{b.class}:" 
puts b.bar 

Chạy nó mang lại:

Calling 'bar' on b of type B: 
- method_missing (bar) on b. Redeirecting to b.foo 
- method_missing (bar) on b. Calling super 
- Method defined directly on an instance of B 
- instance method defined by B 

Câu hỏi của tôi là:

Kể từ khi tôi kêu gọi b.bar (trên đối tượng), làm thế nào mà dụ của lớp phương pháp được gọi trước khi phương pháp dụ của objet được gọi là?

tôi dự kiến ​​sẽ có b.method_missing(method) được gọi là đầu tiên, sau đó của lớp dụ method_missing(method) (kể từ khi tôi đang kêu gọi siêu? Nhưng siêu là lớp phân cấp ...) mà không chuyển hướng bar-foo. Ngoài ra, làm thế nào đến, sau khi được chuyển hướng đến foo, missing_method của thể hiện được gọi là? Chúng tôi đã được thông báo rằng chúng tôi đang được chuyển hướng ...

Tôi nghĩ rằng tôi không hiểu khái niệm về cách Ruby cho phép xác định phương pháp thể hiện trên một cá thể của một lớp (mới đối với tôi), trái ngược với định nghĩa nó như là một phương thức thể hiện của một lớp (các ngôn ngữ cổ điển).

Tôi hy vọng câu hỏi này có ý nghĩa, có lẽ đầu tôi vẫn còn quay từ đêm qua ...

+1

tôi đã xóa mã không liên quan để làm cho vấn đề trở nên rõ ràng hơn. Nói chung là một ý tưởng hay để cung cấp một ví dụ * tối thiểu * của một vấn đề. –

Trả lời

4

Vấn đề là đầu ra của bạn không phản ánh thứ tự thực tế thực hiện. Chúng ta hãy nhìn vào kết quả:

method_missing (bar) on b. Redeirecting to b.foo 
method_missing (bar) on b. Calling super 

Thoạt nhìn, điều này mang lại ấn tượng rằng B#method_missing được gọi trước khi phương pháp singleton b.method_missing điều này làm tăng hai câu hỏi bạn mô tả. Trên thực tế, mặc dù, b.method_missing được gọi chính xác trước tiên. Điều này được rõ ràng nếu bạn nhìn vào cách thức tuyên bố puts b.bar được đánh giá:

  1. b không có phương pháp bar, vì vậy b.method_missing được gọi với chuỗi 'bar' như một cuộc tranh cãi.
  2. b.method_missing lần lượt gọi phương thức B#method_missing thông qua việc sử dụng từ khóa super.
  3. B#method_missing sử dụng puts để sản xuất các dòng đầu tiên nhìn thấy trên
  4. phương pháp singleton b.foo được gọi
  5. ngoài cùng puts được thực hiện, trong đó kết quả đầu ra các chuỗi trong b.method_missing cùng với giá trị trả về của b.foo
+2

+1; đánh tôi với nó –

+0

Niklas, cảm ơn vì đã làm rõ (và xóa mã không liên quan). Cảm ơn bạn vì câu trả lời! – dynex

+0

Chạy nó trong trình gỡ rối tất nhiên làm rõ nó. Tôi nên làm điều đó để bắt đầu - xin lỗi các bạn, và cảm ơn sự kiên nhẫn của bạn. – dynex

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