2010-04-21 10 views
14

Mi chiedevo come accedere a una funzione globale fn in ruby ​​da una classe che ha definito anche un metodo fn. Ho fatto una soluzione creando un alias per la funzione in questo modo:Come accedere a una funzione globale (ombreggiata) in ruby ​​

 
def fn 
end 

class Bar 
    alias global_fn fn 
    def fn 
     # how to access the global fn here without the alias 
     global_fn 
    end 
end 

che sto cercando qualcosa lungo le linee di C++ s ':: per accedere portata globale, ma io non riesco a trovare tutte le informazioni su di esso. Immagino di non sapere esattamente quello che sto cercando.

risposta

16

Al livello superiore un def aggiunge un metodo privato a Object.

Mi vengono in mente tre modi per ottenere la funzione di primo livello:

(1) Utilizzare send per richiamare il metodo privato sul Object stesso (funziona solo se il metodo non è un mutatore dal Object sarà la ricevitore)

Object.send(:fn) 

(2) Ottenere un'istanza Method del metodo di primo livello e si legano alla istanza che si desidera richiamare su:

class Bar 
    def fn 
    Object.instance_method(:fn).bind(self).call 
    end 
end 

(3) Utilizzare super (non si assume alcuna super classi di Bar sotto Object ridefiniscono la funzione)

class Bar 
    def fn 
    super 
    end 
end 

UPDATE:

Poiché la soluzione (2) è quella da preferire (a mio parere) che può cercare di migliorare la sintassi per la definizione di un metodo di utilità su Object chiamato super_method:

class Object 
    def super_method(base, meth, *args, &block) 
    if !self.kind_of?(base) 
     raise ArgumentError, "#{base} is not a superclass of #{self}" 
    end 

    base.instance_method(meth).bind(self).call(*args, &block) 
    end 
end 

Utilizzare come la seguente:

class Bar 
    def fn 
    super_method Object, :fn 
    end 
end 

Dove il primo argomento di super_method deve essere una superclasse valida di Bar, il secondo argomento il metodo che si vuole invocare, e tutti i restanti argomenti (se presenti) sono passati lungo come parametri al metodo selezionato.

+0

Non sapevo che i metodi globali vengano effettivamente aggiunti a Object. Questo significa che il mio approccio alias, come il tuo super approccio, si interromperà anche se Bar ha una superclasse che definisce anche fn? –

+0

@yngvedh, esattamente. Si romperà allo stesso modo. L'approccio più generale IMO è quello di utilizzare la seconda soluzione. – horseyguy

+0

@banister, e non c'è altro modo per farlo? Sto pensando a qualcosa di più sintatticamente piacevole, come Object :: fn di C++. –

Problemi correlati