2016-06-22 43 views
1
module Colors 
    Red = 0 
    Blue = 1 
    Green = 2 
end 

zu bekommen, wenn ich den Verweis auf das Modul Colors haben, kann ich den Namen dieses Moduls "Colors" von Colors.name zu bekommen.Wie der Name der Konstante

Ist es möglich, die Zeichenfolgendarstellung der Konstante "Colors::Red" zu erhalten, wenn ich einen Verweis auf die Konstante Colors::Red habe?

+1

Nein, das ist nicht möglich, weil Sie keine Referenz auf die Konstante haben. Sie haben einen Verweis auf den Wert der Konstante. –

Antwort

4

Ja, sofern nur eine Konstante mit einem Wert gleich dem Wert des gegebenen Bezugs hat.

def ref_to_str(color) 
    k = Colors.constants.find { |k| Colors.const_get(k) == color } 
    return nil unless k 
    "Colors::#{k}" 
end 

ref_to_str(Colors::Red) 
    #=> "Colors::Red" 
ref_to_str(Colors::Blue) 
    #=> "Colors::Blue" 
ref_to_str(Colors::Green) 
    #=> "Colors::Green" 
+0

Danke, ich wollte wissen, ob dafür eine eingebaute Methode existiert. – Yeonho

+0

Sie müssen scherzen :) 'Farben' ist _die Konstante_ von absolut gleicher Natur wie 'Colors :: Red'. Sie sind beide Konstanten. Ihre Namen sollen auf dieselbe Weise retrieven werden. Während Ihre Antwort einen zusätzlichen Wert hat und Selbstbeobachtungstechniken usw. demonstriert, ist sie keine Antwort auf die gestellte Frage. Wie Jordan in den Anmerkungen zur ursprünglichen Frage darauf hingewiesen hat, ist es im Allgemeinen unmöglich. Für 'Colors :: Red' referenz, wie in Ihrem Beispiel, wäre die Antwort' Colors :: Red.to_s'. Für "0" ist es mehrdeutig (daher nicht definiert): "Klasse A; A1 = 0; A2 = 0; Ende. – mudasobwa

0

Versuchen Sie es mit constants:

Colors.constants 

so

  • Colors.constants[0].id2name ist Red
  • Colors.constants[1].id2name ist Blue
  • Colors.constants[2].id2name ist Green
+2

Entfernen Sie leere Klammern, um sie zu verwenden, ist kein idiomatischer Rubin. – mudasobwa

+0

Das funktioniert eigentlich nicht. Es bezieht sich nur auf die Reihenfolge, in der die Konstanten im Modul "Farben" aufgeführt sind, und nicht auf den tatsächlichen Wert für jede Konstante. Im angegebenen Beispiel funktioniert dies nur, weil die Sortierreihenfolge und die Werte übereinstimmen. – mayatron

1

Nein, es ist nicht möglich, die Zeichenfolgendarstellung zu erhalten, da sich Colors::Red auf den Wert der Konstante Red bezieht, die im Modul Colors definiert ist.

 Colors::Red => 0      

aber Sie können die Liste der Konstanten für das Modul erhalten mit Colors.constants

 Colors.constants => [:Red, :Blue, :Green] 
1

'Colors' ist nicht der Name der Konstante Colors, ist es der Name der Module, die die konstanten Colors zugewiesen wurde. Es gibt einen fundamentalen Unterschied zwischen Variablen (und ich schließe Konstanten in diesem zusammen mit lokalen Variablen, Instanzvariablen, Klassenvariablen, globalen Variablen, thread-lokalen Pseudo-Globals, method-lokalen Pseudo-Globalen und speziellen Variablen) und Objekte, von denen nicht zuletzt ist, dass Objekte sind, nun, Objekte (duh!) und Variablen sind nicht Objekte! Sie können sie nicht in Variablen speichern, Sie können keine Methoden für sie aufrufen, alles, was Sie tun können, ist ihnen zuzuordnen (zumindest einige davon) und sie zu dereferenzieren. In einer objektorientierten Programmiersprache ist das Methodenaufrufverfahren so gut wie alles, was Sie tun können, und Sie können keine Methoden auf Variablen aufrufen, weil sie keine Objekte sind. Es gibt keine Möglichkeit, Variablenfragen wie " Wie lautet dein Name".

Sie können ein Module für seinen Namen fragen, weil die Module Klasse eine name Instanz Methode, die die Module der Namen zurückgegeben hat. Integer hat keine name Methode, so dass Sie keinen Integer für seinen Namen fragen können.

Beachten Sie, dass der Name einer Module ist etwas "magisch".Es ist nil standardmäßig, aber das erste Mal, dass Sie eine Module einer Konstante zuweisen, wird der Name einige Darstellung des Pfades zu der Konstante (im Grunde die name des einschließenden Moduls + :: + der Name der Konstante). Wenn Sie das Modul jedoch einer anderen Konstanten zuweisen, bleibt der Name auch dann unverändert, wenn Sie die Konstante remove_const haben.

Hier ein netter kleiner Code-Snippet ist, dass die Module#name wirklich gibt den Namen der Module, nicht der Name der Variablen zeigt, verwendet, um es zu verweisen:

m = Module.new 

m.name 
# => nil 

A = m 

m.name 
# => 'A' 

A = nil 
Object.send(:remove_const, :A) # just to be *really* sure 

A 
# NameError: uninitialized constant A 

m.name 
# => 'A' 

Also, kurz gesagt: nein, es Sie können den Namen einer Konstante (oder einer Variablen) nicht aus dem Objekt abrufen, auf das diese Konstante verweist, auch wenn das Objekt nur durch mehr als eine Variable referenziert werden kann. Und welchen Namen würden Sie dann zurückgeben?