2010-04-21 5 views
14

Ich fragte mich, wie auf eine globale Funktion fn in Ruby von einer Klasse zugreifen, die auch eine Methode fn definiert. Ich habe eine Abhilfe gemacht durch die Funktion Aliasing wie so:Wie auf eine (schattierte) globale Funktion in Ruby zugreifen

 
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 

Ich suche nach etwas entlang der Linien von C++ 's :: zu globalen Bereich zugreifen, aber ich kann keine Informationen über sie zu finden scheinen. Ich denke, ich weiß nicht genau, wonach ich suche.

Antwort

16

In der obersten Ebene fügt def eine private Methode zu Object hinzu.

kann ich drei Möglichkeiten denken, die Top-Level-Funktion zu erhalten:

(1) Verwenden Sie send die private Methode auf Object selbst (funktioniert nur zu berufen, wenn das Verfahren nicht ein Mutator ist seit Object das sein wird, Empfänger)

Object.send(:fn) 

(2) Holen Sie sich ein Method Instanz der obersten Ebene Verfahren und binden Sie es an die Instanz, die Sie es aufrufen möchten auf:

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

(3) Verwenden Sie super (nimmt keine Superklassen von Bar unter Object die Funktion neu zu definieren)

class Bar 
    def fn 
    super 
    end 
end 

UPDATE:

Seit Lösung (2) ist die bevorzugte ein (meiner Meinung nach) wir können versuchen, die Syntax durch die Definition eine Hilfsmethode auf Objectsuper_method genannt zu verbessern:

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 

Verwenden Sie wie folgt aus:

class Bar 
    def fn 
    super_method Object, :fn 
    end 
end 

Wo das erste Argument super_method muss eine gültige übergeordnete Klasse von Bar sein, das zweite Argument der Methode, die Sie aufrufen möchten, und alle verbleibenden Argumente (falls vorhanden) entlang als Parameter übergeben zu der ausgewählten Methode.

+0

Ich wusste nicht, dass globale Methoden tatsächlich zum Objekt hinzugefügt werden. Bedeutet dies, dass mein Alias-Ansatz, wie Ihr Super-Ansatz auch auch brechen wird, wenn Bar eine Superklasse hat, die auch Fn definiert? –

+0

@yngvedh, genau. Es wird auf die gleiche Weise brechen. Der allgemeinste Ansatz IMO ist die Verwendung der zweiten Lösung. – horseyguy

+0

@banister, und es gibt keinen anderen Weg, das zu erreichen? Ich denke an etwas, das mehr syntaktisch ansprechend ist, wie zB C++'s Object :: fn. –

Verwandte Themen