2009-06-26 18 views
2

ich die Konstante in dem Modul definieren muß, die die Methode aus der Klasse verwenden, die dieses Modul beinhaltet:Ruby-Modul mit einem statischen Methodenaufruf von Inklusionsklasse

module B 
    def self.included(base) 
    class << base 
    CONST = self.find 
    end 
    end 
end 

class A 
    def self.find 
    "AAA" 
    end 
    include B 
end 

puts A::CONST 

Aber der Compiler gibt den Fehler auf dem vierten Linie.

Gibt es eine andere Möglichkeit, die Konstante zu definieren?

Antwort

2

Je mehr idiomatische Weg, dies in Ruby zu erreichen ist:

module B 
    def self.included(klass) 
    klass.class_eval <<-ruby_eval 
     CONST = find 
    ruby_eval 

    # note that the block form of class_eval won't work 
    # because you can't assign a constant inside a method 
    end 
end 

class A 
    def self.find 
    "AAA" 
    end 
    include B 
end 

puts A::CONST 

Was Sie taten (Klasse < < Basis) Sie tatsächlich metaclass der setzt in den Kontext von A, nicht A selbst. Die find Methode ist auf A selbst, nicht seine Metaklasse. Zu beachten ist, dass Klassen selbst Objekte sind und somit eigene Metaklassen haben.

Um zu versuchen, es deutlicher zu machen:

class Human 
    def parent 
    # this method is on the Human class and available 
    # to all instances of Human. 
    end 

    class << self 
    def build 
     # this method is on the Human metaclass, and 
     # available to its instance, Human itself. 
    end 

    # the "self" here is Human's metaclass, so build 
    # cannot be called. 
    end 

    def self.build 
    # exactly the same as the above 
    end 

    build # the "self" here is Human itself, so build can 
     # be called 
end 

Nicht sicher, ob das hilft, aber wenn Sie es nicht verstehen, können Sie immer noch das class_eval Idiom oben verwenden.

2

In Ihrem speziellen Fall.

module B 
    def self.included(base) 
    base.const_set("CONST", base.find) 
    end 
end 

class A 
    def self.find 
    "AAA" 
    end 
    include B 
end 

puts A::CONST 

Trotz es funktioniert, ist es ein bisschen chaotisch. Sind Sie sicher, dass Sie Ihrem Ziel nicht auf andere Weise folgen können?

+0

Ja, ich erreiche diese Lösung auch. Aber dieser Meta-Aufruf ist keine sehr gute Idee. Gibt es mehr geraden Weg? –

+1

Sie versuchen, zur Laufzeit einen konstanten Wert dynamisch zuzuweisen. AFAIK, andere Wege werden eine "dynamische Konstante Zuweisung" Fehler auslösen. –

0
module B 
    def self.included(base) 
    class << base 
     CONST = self.find 
    end 
    end 
end 

class A 
    class << self 
    def self.find 
     "AAA" 
    end 
    end 
    include B 
end 

dann ist der Compiler Fehler behoben, bitte versuchen Sie es.