2009-11-08 143 views
6

說,我有以下2類:檢測一個方法未被覆蓋

class A 
    def a_method 
    end 
end 

class B < A 
end 

是否有可能從(的實例)類B中方法a_method在所定義的範圍內檢測超類,因此不會在B中被覆蓋?

更新:解決方案

雖然我已經打上查克的回答是「接受」,後來保羅Perrota讓我意識到,該解決方案能夠明顯更簡單,而且它可能會與早期版本的工作Ruby也是。

檢測是否「a_method」在B被覆蓋:

B.instance_methods(false).include?("a_method") 

而對於類方法,我們使用singleton_methods類似:

B.singleton_methods(false).include?("a_class_method") 

回答

7

如果您使用的是Ruby 1.8.7或更高版本,使用Method#owner/UnboundMethod#owner很容易。

class Module 
    def implements_instance_method(method_name) 
    instance_method(method_name).owner == self 
    rescue NameError 
    false 
    end 
end 
+0

非常酷,謝謝!看到最初提到的Ruby版本後,特別高興從1.9降低到1.8.7(我實際使用它)。 – mxgrn 2009-11-08 23:34:55

+0

是的,我對此有點模糊。起初我認爲它與1.8.7一起工作,然後看到'Method#owner'不在1.8.7 ri文檔中,所以我將它改爲1.9,然後我實際檢查了1.8.7中是否存在該方法,並看到我第一次做對了。很高興它有幫助。 – Chuck 2009-11-08 23:55:10

0

可以隨時以下,看看它的存在定義:

a = A.new 

a.methods.include?(:method) 
+0

的OP被詢問如何檢測*從類B *內,如果它覆蓋方法或沒有。 知道類A定義的方法並沒有說類B是否重寫它。 – 2009-11-08 20:10:38

+0

這很好,但是如何另外檢測該方法是否(最初)包含在B的實例方法中? – mxgrn 2009-11-08 20:12:50

+0

在b中,你仍然可以看到A是否響應該方法,如果是這樣,B定義了相同的方法,那麼它明顯優先於A的實現 – ennuikiller 2009-11-08 20:14:59

0

給定一個對象b這是一個實例B,你可以測試一下,看看b的直接超類是否有a_method

b.class.superclass.instance_methods.include? 'a_method' 

注意,測試是針對方法的名稱,而不是一個符號或方法的對象。

「因此沒有被覆蓋在B」 - 只要知道僅在規定的方法是困難的,因爲你可以在A和B的單個實例定義的方法......所以我認爲這將難以測試a_method僅在A上定義,因爲您必須整理系統中的所有子類和子類並對它們進行測試...

2
class A 
    def m1; end 
    def m2; end 
end 

class B < A 
    def m1; end 
    def m3; end 
end 

obj = B.new 
methods_in_class = obj.class.instance_methods(false) # => ["m1", "m3"] 
methods_in_superclass = obj.class.superclass.instance_methods(false) # => ["m2", "m1"] 
methods_in_superclass - methods_in_class # => ["m2"]