在Ruby中实现枚举习语的最佳方法是什么?我正在寻找一些东西,我可以使用(几乎)像Java/ c#枚举。


当前回答

另一种解决方案是使用OpenStruct。它非常简单明了。

https://ruby-doc.org/stdlib-2.3.1/libdoc/ostruct/rdoc/OpenStruct.html

例子:

# bar.rb
require 'ostruct' # not needed when using Rails

# by patching Array you have a simple way of creating a ENUM-style
class Array
   def to_enum(base=0)
      OpenStruct.new(map.with_index(base).to_h)
   end
end

class Bar

    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"
        end
    end

end

# 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'

其他回答

大多数人使用符号(即:foo_bar语法)。它们是一种独特的不透明值。符号不属于任何枚举类型,所以它们不是C的枚举类型的忠实表示,但这几乎是最好的。

我认为实现类似类型的枚举的最好方法是使用符号,因为它们的行为非常像整数(当涉及到性能时,object_id用于进行比较);你不需要担心索引,它们在你的代码xD中看起来非常整洁

最常用的方法是使用符号。例如,不要:

enum {
  FOO,
  BAR,
  BAZ
}

myFunc(FOO);

...你可以使用符号:

# 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)

这比枚举更开放一些,但它很适合Ruby精神。

符号的表现也很好。例如,比较两个相等的符号要比比较两个字符串快得多。

最近我们发布了一个在Ruby中实现枚举的gem。在我的帖子中,你会找到你的问题的答案。我还描述了为什么我们的实现比现有的更好(实际上在Ruby中有很多这个特性的实现)。

如果您担心符号的拼写错误,请确保您的代码在访问具有不存在键的值时引发异常。你可以使用fetch而不是[]:

my_value = my_hash.fetch(:key)

或者在默认情况下,如果你提供了一个不存在的键,让哈希抛出一个异常:

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

如果散列已经存在,你可以添加异常引发行为:

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

通常情况下,您不必担心常量的拼写安全问题。如果你拼错了常量名,通常会引发异常。