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

其他回答

有时我所需要的是能够获取enum的值,并识别其名称类似于java世界。

module Enum
     def get_value(str)
       const_get(str)
     end
     def get_name(sym)
       sym.to_s.upcase
     end
 end

 class Fruits
   include Enum
   APPLE = "Delicious"
   MANGO = "Sweet"
 end

 Fruits.get_value('APPLE') #'Delicious'
 Fruits.get_value('MANGO') # 'Sweet'

 Fruits.get_name(:apple) # 'APPLE'
 Fruits.get_name(:mango) # 'MANGO'

这对我来说是枚举的目的,并保持它非常可扩展。您可以向Enum类添加更多的方法,并且viola可以在所有已定义的Enum中免费获得它们。为例。Get_all_names之类的。

另一种方法是使用带有包含名称和值的散列的Ruby类,如下面的RubyFleebie博客文章所述。这允许您轻松地在值和常量之间进行转换(特别是如果您添加了一个类方法来查找给定值的名称)。

符号是红宝石之道。然而,有时我们需要与一些C代码或Java进行对话,这些代码或Java会为各种事情公开一些枚举。


#server_roles.rb
module EnumLike

  def EnumLike.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
  end

end

然后可以这样使用


require 'server_roles'

sSymb, sEnum =EnumLike.server_role()

foreignvec[sEnum[:SERVER_WORKSTATION]]=8

这当然可以是抽象的,你可以滚动我们自己的Enum类

也许最好的轻量级方法是

module MyConstants
  ABC = Class.new
  DEF = Class.new
  GHI = Class.new
end

这样,值就有了关联的名称,就像在Java/ c#中一样:

MyConstants::ABC
=> MyConstants::ABC

要获得所有的值,可以这样做

MyConstants.constants
=> [:ABC, :DEF, :GHI] 

如果你想要枚举的序号值,你可以这样做

MyConstants.constants.index :GHI
=> 2
module Status
  BAD  = 13
  GOOD = 24

  def self.to_str(status)
    for sym in self.constants
      if self.const_get(sym) == status
        return sym.to_s
      end
    end
  end

end


mystatus = Status::GOOD

puts Status::to_str(mystatus)

输出:

GOOD