@auramo, gute Frage und gute Wahl für die beste Antwort. Liebe es oder hasse es, du bekommst keine Typensicherheit und (zumindest in Ruby) keine Tippfehler. Ich war begeistert, als ich Enums in C # und später in Java entdeckte (wählen Sie einen Wert aus, aber aus diesen!). Ruby bietet auf keinen Fall eine echte Möglichkeit, dies zu tun.
Dan Rosenstark
2
Das Problem bei dieser Frage ist, dass Java- und C # -Aufzählungen dramatisch unterschiedliche Dinge sind. Ein Java-Enum-Member ist eine Objektinstanz und ein Singleton. Eine Java-Enumeration kann einen Konstruktor haben. Im Gegensatz dazu basieren C # -Aufzählungen auf primitiven Werten. Welches Verhalten sucht der Fragesteller? Während es wahrscheinlich der Fall ist, dass der C # -Fall gewünscht wird, wird Java explizit erwähnt und nicht C oder C ++, daher gibt es einige Zweifel. Der Hinweis, dass es in Ruby keine Möglichkeit gibt, "sicher" zu sein, ist transparent falsch, aber Sie müssen etwas Anspruchsvolleres implementieren.
user1164178
Antworten:
317
Zwei Wege. Symbole ( :fooNotation) oder Konstanten ( FOONotation).
Symbole sind geeignet, wenn Sie die Lesbarkeit verbessern möchten, ohne Code mit Literalzeichenfolgen zu verunreinigen.
Konstanten sind angemessen, wenn Sie einen wichtigen zugrunde liegenden Wert haben. Deklarieren Sie einfach ein Modul, das Ihre Konstanten enthält, und deklarieren Sie dann die darin enthaltenen Konstanten.
moduleFoo
BAR =1
BAZ =2
BIZ =4end
flags =Foo::BAR |Foo::BAZ # flags = 3
Was ist, wenn diese Aufzählung auch in der Datenbank gespeichert wird? Funktioniert die Symbolnotation? Ich bezweifle ...
Phương Nguyễn
Ich würde den Konstantenansatz verwenden, wenn ich in einer Datenbank speichern würde. Natürlich müssen Sie dann eine Art Suche durchführen, wenn Sie die Daten wieder aus der Datenbank ziehen. Sie können auch etwas wie :minnesota.to_sbeim Speichern in einer Datenbank verwenden, um die Zeichenfolgenversion des Symbols zu speichern. Ich glaube, Rails hat einige Hilfsmethoden, um mit einigen davon umzugehen.
mlibby
7
Wäre ein Modul nicht besser, um Konstanten zu gruppieren - da Sie keine Instanzen davon erstellen werden?
Thomthom
3
Nur ein Kommentar. Ruby ist ein bisschen nervig, wenn es darum geht, Konventionen zu benennen, aber nicht wirklich offensichtlich, bis Sie darüber stolpern. Die Namen der Aufzählungen müssen alle Großbuchstaben sein und der erste Buchstabe des Modulnamens muss groß geschrieben werden, damit Ruby weiß, dass das Modul ein Modul von Konstanten ist.
Rokujolady
3
Nicht ganz richtig. Der erste Buchstabe der Konstante muss groß geschrieben werden, aber nicht alle Buchstaben müssen groß geschrieben werden. Dies ist eine Frage der Konventionspräferenz. Beispielsweise sind alle Modul- und Klassennamen auch Konstanten.
Michael Brown
59
Ich bin überrascht, dass niemand so etwas angeboten hat (geerntet aus dem RAPI- Juwel):
classEnum
private
defself.enum_attr(name, num)
name = name.to_s
define_method(name +'?')do@attrs& num !=0end
define_method(name +'=')do|set|if set
@attrs|= num
else@attrs&=~num
endendend
public
def initialize(attrs =0)@attrs= attrs
enddef to_i
@attrsendend
Dies funktioniert gut in Datenbankszenarien oder beim Umgang mit Konstanten / Aufzählungen im C-Stil (wie dies bei der Verwendung von FFI der Fall ist , das RAPI in großem Umfang verwendet).
Außerdem müssen Sie sich keine Sorgen über Tippfehler machen, die stille Fehler verursachen, wie Sie es bei der Verwendung einer Hash-Lösung tun würden.
Das ist eine großartige Möglichkeit, dieses spezielle Problem zu lösen, aber der Grund, warum niemand vorgeschlagen hat, hat wahrscheinlich damit zu tun, dass es nicht viel mit C # / Java-Enums zu tun hat.
mlibby
1
Dies ist etwas unvollständig, dient aber als guter Hinweis darauf, wie Sie Lösungen mit einem dynamischen Ansatz implementieren können. Es hat eine gewisse Ähnlichkeit mit einer C # -Aufzählung mit dem FlagsAttribute-Satz, aber wie die obigen symbol- / konstantenbasierten Lösungen ist es eine Antwort von vielen. Das Problem ist die ursprüngliche Frage, die in ihrer Absicht durcheinander ist (C # und Java sind nicht austauschbar). Es gibt viele Möglichkeiten, Objekte in Ruby aufzulisten. Die Auswahl des richtigen hängt vom zu lösenden Problem ab. Das sklavische Replizieren von Funktionen, die Sie nicht benötigen, ist falsch. Die richtige Antwort muss vom Kontext abhängen.
user1164178
52
Der idiomatischste Weg, dies zu tun, ist die Verwendung von Symbolen. Zum Beispiel anstelle von:
enum {
FOO,
BAR,
BAZ
}
myFunc(FOO);
... Sie können nur Symbole verwenden:
# You don't actually need to declare these, of course--this is# just to show you what symbols look like.:foo
:bar
:baz
my_func(:foo)
Dies ist etwas offener als Aufzählungen, passt aber gut zum Ruby-Geist.
Symbole funktionieren auch sehr gut. Das Vergleichen von zwei Symbolen auf Gleichheit ist beispielsweise viel schneller als das Vergleichen von zwei Zeichenfolgen.
Der Ruby-Geist lautet also: "Tippfehler werden kompiliert"
mxcl
82
Beliebte Ruby-Frameworks stützen sich stark auf die Metaprogrammierung zur Laufzeit, und eine zu lange Überprüfung der Ladezeit würde Rubys Ausdruckskraft den größten Teil nehmen. Um Probleme zu vermeiden, üben die meisten Ruby-Programmierer testgetriebenes Design, bei dem nicht nur Tippfehler, sondern auch Logikfehler auftreten.
Emk
10
@yar: Nun, Sprachdesign ist eine Reihe von Kompromissen, und Sprachfunktionen interagieren. Wenn Sie eine gute, hochdynamische Sprache wollen, gehen Sie mit Ruby, schreiben Sie zuerst Ihre Unit-Tests und gehen Sie mit dem Geist der Sprache. :-) Wenn Sie nicht danach suchen, gibt es Dutzende anderer hervorragender Sprachen, von denen jede unterschiedliche Kompromisse eingeht.
Emk
10
@emk, ich stimme zu, aber mein persönliches Problem ist, dass ich mich in Ruby sehr wohl fühle, aber ich fühle mich nicht wohl, wenn ich in Ruby umgestalte. Und jetzt, da ich (endlich) angefangen habe, Unit-Tests zu schreiben, stelle ich fest, dass sie kein Allheilmittel sind: Ich vermute, 1) dass Ruby-Code in der Praxis nicht so oft massiv überarbeitet wird und 2) Ruby nicht das Ende ist -of-the-line in Bezug auf dynamische Sprachen, gerade weil es schwierig ist, automatisch umzugestalten. Siehe meine Frage 2317579, die seltsamerweise von den Smalltalk-Leuten übernommen wurde.
Dan Rosenstark
4
Ja, aber die Verwendung dieser Zeichenfolgen wäre nicht im Sinne der C # -Sprache, es ist einfach eine schlechte Praxis.
Es wird eine Überprüfung der Kompilierungszeit durchgeführt (im Gegensatz zur Verwendung von Symbolen).
Ich kann leicht auf die Liste aller möglichen Werte zugreifen: nur MY_ENUM
Ich kann leicht auf verschiedene Werte zugreifen: MY_VALUE_1
Es kann Werte jeden Typs haben, nicht nur Symbol
Symbole sind möglicherweise besser, da Sie den Namen der äußeren Klasse nicht schreiben müssen, wenn Sie ihn in einer anderen Klasse verwenden ( MyClass::MY_VALUE_1)
Ich denke, das ist die beste Antwort. Die Funktionalität, Syntax und der minimale Code-Overhead kommen Java / C # am nächsten. Außerdem können Sie die Definitionen noch tiefer als eine Ebene verschachteln und dennoch alle Werte mit MyClass :: MY_ENUM.flatten wiederherstellen. Als Randnotiz würde ich hier Großbuchstaben verwenden, wie es der Standard für Konstanten in Ruby ist. MyClass :: MyEnum wird möglicherweise mit einem Verweis auf eine Unterklasse verwechselt.
Janosch
@Janosch, ich habe die Namen aktualisiert. danke für den Vorschlag
Alexey
Ich bin immer noch ein wenig verwirrt und der Link 410 (nein, nicht 404). Können Sie Beispiele geben, wie diese Aufzählung verwendet wird?
Shelvacu
17
Wenn Sie Rails 4.2 oder höher verwenden, können Sie Rails-Aufzählungen verwenden.
Rails hat jetzt standardmäßig Aufzählungen, ohne dass Edelsteine eingefügt werden müssen.
Dies ist Java, C ++ - Enums sehr ähnlich (und mehr mit Funktionen).
Wie Sie sagten - nicht nützlich, wenn das OP keine Rails verwendet (oder genauer gesagt, das Objekt ist nicht vom Typ ActiveRecord). Nur meine Ablehnung zu erklären, ist alles.
Ger
2
Dies sind keine Aufzählungen in Ruby, sondern eine ActiveRecord-Schnittstelle zu Aufzählungen in Ihrer Datenbank. Keine verallgemeinerbare Lösung, die in jedem anderen Anwendungsfall angewendet werden kann.
Adam Lassek
Ich habe das bereits in meiner Antwort erwähnt.
Vedant
Dies ist die beste Antwort IFF mit Rails.
theUtherSide
Ich mag es nicht, weil es in einer Rails-Datenbank gespeichert werden muss (um zu funktionieren) und weil es erlaubt, viele Instanzen der ConversationKlasse zu erstellen - ich glaube, es darf nur eine Instanz zulassen.
Prograils
8
Dies ist meine Herangehensweise an Aufzählungen in Ruby. Ich war kurz und bündig, nicht unbedingt der C-artigste. Irgendwelche Gedanken?
IMHO repliziert dies sehr genau die Verwendung und den Zweck (Typensicherheit) von Java, außerdem können Konstanten vorzugsweise wie class ABC; end
folgt
8
Ich weiß, es ist lange her, dass der Typ diese Frage gestellt hat, aber ich hatte die gleiche Frage und dieser Beitrag gab mir keine Antwort. Ich wollte eine einfache Möglichkeit, um zu sehen, was die Zahl darstellt, einen einfachen Vergleich und vor allem ActiveRecord-Unterstützung für die Suche anhand der Spalte, die die Aufzählung darstellt.
Ich habe nichts gefunden, also habe ich eine großartige Implementierung namens yinum gemacht, die alles erlaubte, was ich suchte. Ich habe eine Menge Spezifikationen erstellt, daher bin ich mir ziemlich sicher, dass es sicher ist.
Wenn Sie sich Sorgen über Tippfehler mit Symbolen machen, stellen Sie sicher, dass Ihr Code eine Ausnahme auslöst, wenn Sie auf einen Wert mit einem nicht vorhandenen Schlüssel zugreifen. Sie können dies tun, indem Sie fetchanstatt []:
my_value = my_hash.fetch(:key)
oder indem der Hash standardmäßig eine Ausnahme auslöst, wenn Sie einen nicht vorhandenen Schlüssel angeben:
my_hash =Hash.new do|hash, key|
raise "You tried to access using #{key.inspect} when the only keys we have are #{hash.keys.inspect}"end
Wenn der Hash bereits vorhanden ist, können Sie das Verhalten zum Auslösen von Ausnahmen hinzufügen:
my_hash =Hash[[[1,2]]]
my_hash.default_proc = proc do|hash, key|
raise "You tried to access using #{key.inspect} when the only keys we have are #{hash.keys.inspect}"end
Normalerweise müssen Sie sich keine Sorgen um die Tippfehlersicherheit mit Konstanten machen. Wenn Sie einen konstanten Namen falsch schreiben, wird normalerweise eine Ausnahme ausgelöst.
Anscheinend befürworten Sie das Emulieren von Aufzählungen mit Hashes , ohne dies ausdrücklich zu sagen. Es könnte eine gute Idee sein, Ihre Antwort zu bearbeiten, um dies zu sagen. (Ich habe auch noch einen Bedarf für so etwas wie Aufzählungen in Ruby, und mein erster Ansatz , es zu lösen , ist durch Hashes mit: FOO_VALUES = {missing: 0, something: 1, something_else: 2, ...}Dies definiert die Tastensymbole. missing, somethingUsw., und mache auch vergleichbar sie über die zugehörigen Werte.)
Teemu Leisti
Ich meine, ohne es gleich zu Beginn der Antwort zu sagen.
Teemu Leisti
4
Jemand ging voran und schrieb einen Rubinstein namens Renum . Es wird behauptet, das nächstgelegene Java / C # -ähnliche Verhalten zu erhalten. Persönlich lerne ich immer noch Ruby und war ein wenig schockiert, als ich wollte, dass eine bestimmte Klasse eine statische Aufzählung enthält, möglicherweise einen Hash, der über Google nicht so einfach zu finden ist.
Ich habe noch nie eine Aufzählung in Ruby gebraucht. Symbole und Konstanten sind idiomatisch und lösen dieselben Probleme, nicht wahr?
Chuck
Wahrscheinlich Chuck; Aber wenn Sie nach einer Aufzählung in Rubin googeln, kommen Sie nicht so weit. Es zeigt Ihnen Ergebnisse für den besten Versuch der Menschen, ein direktes Äquivalent zu finden. Was mich wundert, vielleicht ist es etwas Schönes, das Konzept zusammen zu packen.
Dlamblin
@Chuck Symbole und Konstanten erzwingen nicht, dass ein Wert einer kleinen Menge von Werten sein muss.
David Moles
3
Es hängt alles davon ab, wie Sie Java- oder C # -Aufzählungen verwenden. Wie Sie es verwenden, bestimmt die Lösung, die Sie in Ruby auswählen.
Probieren Sie den nativen SetTyp aus, zum Beispiel:
Kürzlich haben wir eine veröffentlicht Juwel veröffentlicht , das Enums in Ruby implementiert . In meinem Beitrag finden Sie die Antworten auf Ihre Fragen. Außerdem habe ich dort beschrieben, warum unsere Implementierung besser ist als die vorhandenen (tatsächlich gibt es viele Implementierungen dieser Funktion in Ruby noch als Juwelen).
# bar.rb
require 'ostruct'# not needed when using Rails# by patching Array you have a simple way of creating a ENUM-styleclassArraydef to_enum(base=0)OpenStruct.new(map.with_index(base).to_h)endendclassBar
MY_ENUM =OpenStruct.new(ONE:1, TWO:2, THREE:3)
MY_ENUM2 =%w[ONE TWO THREE].to_enum
def use_enum (value)case value
when MY_ENUM.ONE
puts "Hello, this is ENUM 1"when MY_ENUM.TWO
puts "Hello, this is ENUM 2"when MY_ENUM.THREE
puts "Hello, this is ENUM 3"else
puts "#{value} not found in ENUM"endendend# usage
foo =Bar.new
foo.use_enum 1
foo.use_enum 2
foo.use_enum 9# put this code in a file 'bar.rb', start IRB and type: load 'bar.rb'
Symbole ist der Rubinweg. Manchmal muss man jedoch mit C-Code oder etwas anderem oder Java sprechen, das eine Aufzählung für verschiedene Dinge verfügbar macht.
#server_roles.rbmoduleEnumLikedefEnumLike.server_role
server_Symb=[:SERVER_CLOUD,:SERVER_DESKTOP,:SERVER_WORKSTATION]
server_Enum=Hash.new
i=0
server_Symb.each{|e| server_Enum[e]=i; i +=1}return server_Symb,server_Enum
endend
Großschreiben Sie das zweite Wort in Variablen (z. B. server_Symb) aus einem bestimmten Grund? Sofern es keinen bestimmten Grund gibt, ist es idiomatisch für Variablen snake_case_with_all_lower_caseund für Symbole :lower_case.
Andrew Grimm
1
@ Andrew; Dieses Beispiel stammt aus der Praxis, und in der Netzwerkprotokolldokumentation wurde xxx_Yyy verwendet, sodass der Code in mehreren Sprachen dasselbe Konzept verwendete, sodass Änderungen der Spezifikation verfolgt werden konnten.
Jonke
1
Code Golf : server_Symb.each_with_index { |e,i| server_Enum[e] = i}. Keine Notwendigkeit für i = 0.
Andrew Grimm
2
Ich habe solche Aufzählungen implementiert
moduleEnumTypedefself.find_by_id id
if id.instance_of?String
id = id.to_i
end
values.each do|type|if id == type.id
return type
endendnilenddefself.values
[@ENUM_1,@ENUM_2]endclassEnum
attr_reader :id,:label
def initialize id, label
@id= id
@label= label
endend@ENUM_1=Enum.new(1,"first")@ENUM_2=Enum.new(2,"second")end
Dies scheint ein bisschen überflüssig zu sein, aber dies ist eine Methode, die ich einige Male verwendet habe, insbesondere wenn ich in XML oder ähnliches integriere.
Ich würde diesen Ansatz nicht empfehlen, da Sie die Werte manuell einstellen und sicherstellen müssen, dass Sie die richtige Reihenfolge erhalten :VAL. Es wäre besser, mit einem Array zu beginnen und den Hash mit.map.with_index
DaveMongoose
1
Der genaue Punkt ist, sich an einen Wert zu binden, der von Dritten vorgegeben wird. Es geht nicht um Erweiterbarkeit an sich, sondern darum, sich mit externen Einschränkungen befassen zu müssen, die sich auf die Berechenbarkeit innerhalb Ihrer Prozessgrenzen auswirken.
JJJ
Gutes Argument! In diesem Fall ist es definitiv sinnvoll, die Werte anzugeben, aber ich würde gerne die umgekehrte Suche mit .keyoder .invertanstelle eines :VALSchlüssels durchführen ( stackoverflow.com/a/10989394/2208016 )
DaveMongoose
Ja, das ist (wieder bei dir) ein fairer Punkt. Mein Rubin war unelegant und unhandlich. Würde auf keyinvert
jeden Fall
1
Die meisten Leute benutzen Symbole (das ist die :foo_barSyntax). Sie sind eine Art einzigartige undurchsichtige Werte. Symbole gehören zu keinem Aufzählungstyp, daher sind sie keine getreue Darstellung des Aufzählungstyps von C, aber das ist so gut wie es nur geht.
Manchmal ist alles, was ich brauche, in der Lage zu sein, den Wert von enum abzurufen und seinen Namen ähnlich wie in der Java-Welt zu identifizieren.
moduleEnumdef get_value(str)
const_get(str)enddef get_name(sym)
sym.to_s.upcase
endendclassFruits
include Enum
APPLE ="Delicious"
MANGO ="Sweet"endFruits.get_value('APPLE')#'Delicious'Fruits.get_value('MANGO')# 'Sweet'Fruits.get_name(:apple)# 'APPLE'Fruits.get_name(:mango)# 'MANGO'
Dies dient für mich dem Zweck der Aufzählung und hält es auch sehr erweiterbar. Sie können der Enum-Klasse weitere Methoden hinzufügen, und Viola erhält sie in allen definierten Enums kostenlos. zum Beispiel. get_all_names und ähnliches.
Ein anderer Ansatz besteht darin, eine Ruby-Klasse mit einem Hash zu verwenden, der Namen und Werte enthält, wie im folgenden RubyFleebie-Blogbeitrag beschrieben . Auf diese Weise können Sie problemlos zwischen Werten und Konstanten konvertieren (insbesondere, wenn Sie eine Klassenmethode hinzufügen, um den Namen für einen bestimmten Wert zu suchen).
Ich denke, der beste Weg, um Aufzählungstypen zu implementieren, sind Symbole, da sich diese so ziemlich wie Ganzzahlen verhalten (wenn es um die Leistung geht, wird object_id verwendet, um Vergleiche anzustellen). Sie müssen sich keine Gedanken über die Indizierung machen und sie sehen in Ihrem Code xD wirklich gut aus
Eine andere Möglichkeit, eine Aufzählung mit konsequenter Gleichstellungsbehandlung nachzuahmen (schamlos von Dave Thomas übernommen). Ermöglicht offene Aufzählungen (ähnlich wie Symbole) und geschlossene (vordefinierte) Aufzählungen.
Antworten:
Zwei Wege. Symbole (
:foo
Notation) oder Konstanten (FOO
Notation).Symbole sind geeignet, wenn Sie die Lesbarkeit verbessern möchten, ohne Code mit Literalzeichenfolgen zu verunreinigen.
Konstanten sind angemessen, wenn Sie einen wichtigen zugrunde liegenden Wert haben. Deklarieren Sie einfach ein Modul, das Ihre Konstanten enthält, und deklarieren Sie dann die darin enthaltenen Konstanten.
quelle
:minnesota.to_s
beim Speichern in einer Datenbank verwenden, um die Zeichenfolgenversion des Symbols zu speichern. Ich glaube, Rails hat einige Hilfsmethoden, um mit einigen davon umzugehen.Ich bin überrascht, dass niemand so etwas angeboten hat (geerntet aus dem RAPI- Juwel):
Welches kann so verwendet werden:
Beispiel:
Dies funktioniert gut in Datenbankszenarien oder beim Umgang mit Konstanten / Aufzählungen im C-Stil (wie dies bei der Verwendung von FFI der Fall ist , das RAPI in großem Umfang verwendet).
Außerdem müssen Sie sich keine Sorgen über Tippfehler machen, die stille Fehler verursachen, wie Sie es bei der Verwendung einer Hash-Lösung tun würden.
quelle
Der idiomatischste Weg, dies zu tun, ist die Verwendung von Symbolen. Zum Beispiel anstelle von:
... Sie können nur Symbole verwenden:
Dies ist etwas offener als Aufzählungen, passt aber gut zum Ruby-Geist.
Symbole funktionieren auch sehr gut. Das Vergleichen von zwei Symbolen auf Gleichheit ist beispielsweise viel schneller als das Vergleichen von zwei Zeichenfolgen.
quelle
Ich benutze den folgenden Ansatz:
Ich mag es für die folgenden Vorteile:
MY_ENUM
MY_VALUE_1
Symbole sind möglicherweise besser, da Sie den Namen der äußeren Klasse nicht schreiben müssen, wenn Sie ihn in einer anderen Klasse verwenden (
MyClass::MY_VALUE_1
)quelle
Wenn Sie Rails 4.2 oder höher verwenden, können Sie Rails-Aufzählungen verwenden.
Rails hat jetzt standardmäßig Aufzählungen, ohne dass Edelsteine eingefügt werden müssen.
Dies ist Java, C ++ - Enums sehr ähnlich (und mehr mit Funktionen).
Zitiert von http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html :
quelle
Conversation
Klasse zu erstellen - ich glaube, es darf nur eine Instanz zulassen.Dies ist meine Herangehensweise an Aufzählungen in Ruby. Ich war kurz und bündig, nicht unbedingt der C-artigste. Irgendwelche Gedanken?
quelle
Schauen Sie sich das Rubin-Enum-Juwel https://github.com/dblock/ruby-enum an .
quelle
Vielleicht wäre der beste leichte Ansatz
Auf diese Weise haben Werte Namen wie in Java / C #:
Um alle Werte zu erhalten, können Sie dies tun
Wenn Sie den Ordnungswert einer Aufzählung möchten, können Sie dies tun
quelle
class ABC; end
Ich weiß, es ist lange her, dass der Typ diese Frage gestellt hat, aber ich hatte die gleiche Frage und dieser Beitrag gab mir keine Antwort. Ich wollte eine einfache Möglichkeit, um zu sehen, was die Zahl darstellt, einen einfachen Vergleich und vor allem ActiveRecord-Unterstützung für die Suche anhand der Spalte, die die Aufzählung darstellt.
Ich habe nichts gefunden, also habe ich eine großartige Implementierung namens yinum gemacht, die alles erlaubte, was ich suchte. Ich habe eine Menge Spezifikationen erstellt, daher bin ich mir ziemlich sicher, dass es sicher ist.
Einige Beispielfunktionen:
quelle
Wenn Sie sich Sorgen über Tippfehler mit Symbolen machen, stellen Sie sicher, dass Ihr Code eine Ausnahme auslöst, wenn Sie auf einen Wert mit einem nicht vorhandenen Schlüssel zugreifen. Sie können dies tun, indem Sie
fetch
anstatt[]
:oder indem der Hash standardmäßig eine Ausnahme auslöst, wenn Sie einen nicht vorhandenen Schlüssel angeben:
Wenn der Hash bereits vorhanden ist, können Sie das Verhalten zum Auslösen von Ausnahmen hinzufügen:
Normalerweise müssen Sie sich keine Sorgen um die Tippfehlersicherheit mit Konstanten machen. Wenn Sie einen konstanten Namen falsch schreiben, wird normalerweise eine Ausnahme ausgelöst.
quelle
FOO_VALUES = {missing: 0, something: 1, something_else: 2, ...}
Dies definiert die Tastensymbole.missing
,something
Usw., und mache auch vergleichbar sie über die zugehörigen Werte.)Jemand ging voran und schrieb einen Rubinstein namens Renum . Es wird behauptet, das nächstgelegene Java / C # -ähnliche Verhalten zu erhalten. Persönlich lerne ich immer noch Ruby und war ein wenig schockiert, als ich wollte, dass eine bestimmte Klasse eine statische Aufzählung enthält, möglicherweise einen Hash, der über Google nicht so einfach zu finden ist.
quelle
Es hängt alles davon ab, wie Sie Java- oder C # -Aufzählungen verwenden. Wie Sie es verwenden, bestimmt die Lösung, die Sie in Ruby auswählen.
Probieren Sie den nativen
Set
Typ aus, zum Beispiel:quelle
Set[:a, :b, :c]
?Kürzlich haben wir eine veröffentlicht Juwel veröffentlicht , das Enums in Ruby implementiert . In meinem Beitrag finden Sie die Antworten auf Ihre Fragen. Außerdem habe ich dort beschrieben, warum unsere Implementierung besser ist als die vorhandenen (tatsächlich gibt es viele Implementierungen dieser Funktion in Ruby noch als Juwelen).
quelle
Eine andere Lösung ist die Verwendung von OpenStruct. Es ist ziemlich einfach und sauber.
https://ruby-doc.org/stdlib-2.3.1/libdoc/ostruct/rdoc/OpenStruct.html
Beispiel:
quelle
Symbole ist der Rubinweg. Manchmal muss man jedoch mit C-Code oder etwas anderem oder Java sprechen, das eine Aufzählung für verschiedene Dinge verfügbar macht.
Dies kann dann so verwendet werden
Dies kann natürlich abstrakt gemacht werden und Sie können unsere eigene Enum-Klasse würfeln
quelle
server_Symb
) aus einem bestimmten Grund? Sofern es keinen bestimmten Grund gibt, ist es idiomatisch für Variablensnake_case_with_all_lower_case
und für Symbole:lower_case
.server_Symb.each_with_index { |e,i| server_Enum[e] = i}
. Keine Notwendigkeit füri = 0
.Ich habe solche Aufzählungen implementiert
dann ist es einfach, Operationen durchzuführen
...
...
quelle
Dies scheint ein bisschen überflüssig zu sein, aber dies ist eine Methode, die ich einige Male verwendet habe, insbesondere wenn ich in XML oder ähnliches integriere.
Dies gibt mir die Strenge von ac # enum und es ist an das Modell gebunden.
quelle
:VAL
. Es wäre besser, mit einem Array zu beginnen und den Hash mit.map.with_index
.key
oder.invert
anstelle eines:VAL
Schlüssels durchführen ( stackoverflow.com/a/10989394/2208016 )key
invert
Die meisten Leute benutzen Symbole (das ist die
:foo_bar
Syntax). Sie sind eine Art einzigartige undurchsichtige Werte. Symbole gehören zu keinem Aufzählungstyp, daher sind sie keine getreue Darstellung des Aufzählungstyps von C, aber das ist so gut wie es nur geht.quelle
Ausgabe:
1 - a
2 - b
3 - c
4 - d
quelle
to_enum
gibt Ihnen ein enumera tor , währendenum
in der C # / Java Sinn ist ein enumera tionAusgabe:
quelle
Manchmal ist alles, was ich brauche, in der Lage zu sein, den Wert von enum abzurufen und seinen Namen ähnlich wie in der Java-Welt zu identifizieren.
Dies dient für mich dem Zweck der Aufzählung und hält es auch sehr erweiterbar. Sie können der Enum-Klasse weitere Methoden hinzufügen, und Viola erhält sie in allen definierten Enums kostenlos. zum Beispiel. get_all_names und ähnliches.
quelle
Ein anderer Ansatz besteht darin, eine Ruby-Klasse mit einem Hash zu verwenden, der Namen und Werte enthält, wie im folgenden RubyFleebie-Blogbeitrag beschrieben . Auf diese Weise können Sie problemlos zwischen Werten und Konstanten konvertieren (insbesondere, wenn Sie eine Klassenmethode hinzufügen, um den Namen für einen bestimmten Wert zu suchen).
quelle
Ich denke, der beste Weg, um Aufzählungstypen zu implementieren, sind Symbole, da sich diese so ziemlich wie Ganzzahlen verhalten (wenn es um die Leistung geht, wird object_id verwendet, um Vergleiche anzustellen). Sie müssen sich keine Gedanken über die Indizierung machen und sie sehen in Ihrem Code xD wirklich gut aus
quelle
Eine andere Möglichkeit, eine Aufzählung mit konsequenter Gleichstellungsbehandlung nachzuahmen (schamlos von Dave Thomas übernommen). Ermöglicht offene Aufzählungen (ähnlich wie Symbole) und geschlossene (vordefinierte) Aufzählungen.
quelle
Probieren Sie das Inum. https://github.com/alfa-jpn/inum
Weitere Informationen finden Sie unter https://github.com/alfa-jpn/inum#usage
quelle