方法查找順序


就目前為此,你已經知道實例方法、類別方法與單例方法,也已經看過類別、模組,那麼如果你有個物件o,打算呼叫某個實例方法some,那查找方法的順序為何?大致可循以下順序:
  1. 查看物件是否定義some單例方法
  2. 查看物件的類別是否定義some實例方法
    1. 若類別定義了some實例方法後,再include某模組具有some實例方法,則使用的是模組的some方法
    2. 若類別include某模組具有some實例方法後,再定義了some實例方法,則使用的是類別的some方法
  3. 查看物件的父類別是否定義some實例方法

可以實際撰寫簡單的測試:
>> module M1
>>     def some
>>         puts "M1 some"
>>     end
>> end
=> nil
>> class Some
>>     def some
>>         puts "Some some"
>>     end
>> end
=> nil
>> class Other < Some; end
=> nil
>> Other.new.some
Some some
=> nil
>> 


以上Other僅繼承Some,使用的是繼承下來的實例方法。若再include模組:
>> class Other < Some
>>     include M1
>> end
=> Other
>> Other.new.some
M1 some
=> nil
>> 


模組覆蓋了Some的some定義,使用的是模組的some定義。若再於Other中定義方法:
>> class Other
>>     def some
>>         puts "Other some"
>>     end
>> end
=> nil
>> Other.new.some
Other some
=> nil
>>


再度定義的方法覆蓋了模組的some定義,若再於物件定義單例方法:
>> o = Other.new
=> #<Other:0x27e2a28>
>> def o.some
>>     puts "o some"
>> end
=> nil
>> o.some
o some
=> nil
>>


則單例方法會覆蓋Other定義的some方法。

先前談過,可以使用remove_method移除實例方法,但僅能移除類別中定義的方法,繼承下來的方法或include進來的方法無法移除。例如:
>> class Some
>>     def some
>>         puts "Some some"
>>     end
>> end
=> nil
>> class Other < Some
>>     def some
>>         puts "Other some"
>>     end
>> end
=> nil
>> o = Other.new
=> #<Other:0x212d888>
>> o.some
Other some
=> nil
>> class Other
>>     remove_method :some
>> end
=> Other
>> o.some
Some some
=> nil
>> class Other
>>     remove_method :some
>> end
NameError: method `some' not defined in Other
        from (irb):18:in `remove_method'
        from (irb):18:in `<class:Other>'
        from (irb):17
        from C:/Winware/Ruby192/bin/irb:12:in `<main>'
>>

 
你可以使用undef_method讓方法查找失效,想回復方法查找,可重新於類別中重新定義同名方法。