2009-11-08 22 views
6

dire che ho i seguenti 2 classi:Rilevare che un metodo non è stato ignorato

class A 
    def a_method 
    end 
end 

class B < A 
end 

è possibile rilevare dall'interno (un'istanza) classe B che metodo a_method è solo definita nel superclasse, quindi non viene sovrascritta in B?

Aggiornamento: la soluzione

Mentre ho segnato la risposta di Chuck come "accettato", poi Paolo Perrota mi ha fatto capire che la soluzione apparentemente può essere più semplice, e sarà probabilmente funzionerà con le versioni precedenti di Ruby, anche.

Rilevare se "a_method" viene sovrascritto in B:

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

E per i metodi della classe usiamo singleton_methods simile:

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

risposta

7

Se stai usando Ruby 1.8.7 o superiore, è facile con Method#owner/UnboundMethod#owner.

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

Molto bello, grazie! Soprattutto felice dopo aver visto la versione di Ruby che hai menzionato in precedenza andare giù da 1,9 a 1,8,7 (che sto effettivamente usando). – mxgrn

+0

Sì, ero un po 'confuso su quello. All'inizio ho pensato che funzionasse con 1.8.7, poi ho visto che il 'Method # owner' non era presente nei documenti di 1.8.7 ri, quindi l'ho cambiato in 1.9, quindi ho effettivamente controllato se il metodo esisteva in 1.8.7 e visto che ho avuto ragione la prima volta. Lieto che aiuti. – Chuck

0

si può sempre al seguente e vedere se ci definito:

a = A.new 

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

Il PO sta chiedendo come rilevare * dall'interno di classe B * se l'override del metodo o no. Sapendo che la classe A definisce il metodo non dice se la classe B lo sostituisce o no. –

+0

Questo va bene, ma come rilevare ulteriormente che il metodo è * non * (originariamente) incluso nei metodi di istanza di B? – mxgrn

+0

beh in b puoi ancora vedere se A risponde al metodo, se è così e B definisce lo stesso metodo allora ovviamente sostituisce l'implementazione di A – ennuikiller

0

Dato un oggetto b che è un'istanza di B, è possibile verificare per vedere se superclasse immediata b s' ha a_method:

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

Si noti che il test è contro il nome del metodo, non un simbolo o un oggetto metodo.

"quindi non essere ignorata in B" - solo sapendo che il metodo è definito solo in A è difficile perché è possibile definire il metodo su un individuo istanze di A e B ... quindi penso che sta andando a essere difficile da verificare che a_method è definito solo su A, perché dovresti completare tutte le sottoclassi e le sottocategorie nel sistema e testarle ...

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"] 
Problemi correlati