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.
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? –
@yngvedh, esattamente. Si romperà allo stesso modo. L'approccio più generale IMO è quello di utilizzare la seconda soluzione. – horseyguy
@banister, e non c'è altro modo per farlo? Sto pensando a qualcosa di più sintatticamente piacevole, come Object :: fn di C++. –