在Ruby中实现枚举习语的最佳方法是什么?我正在寻找一些东西,我可以使用(几乎)像Java/ c#枚举。
当前回答
大多数人使用符号(即:foo_bar语法)。它们是一种独特的不透明值。符号不属于任何枚举类型,所以它们不是C的枚举类型的忠实表示,但这几乎是最好的。
其他回答
查看ruby-enum gem, https://github.com/dblock/ruby-enum。
class Gender
include Enum
Gender.define :MALE, "male"
Gender.define :FEMALE, "female"
end
Gender.all
Gender::MALE
我很惊讶,没有人提供以下内容(从RAPI宝石中收获):
class Enum
private
def self.enum_attr(name, num)
name = name.to_s
define_method(name + '?') do
@attrs & num != 0
end
define_method(name + '=') do |set|
if set
@attrs |= num
else
@attrs &= ~num
end
end
end
public
def initialize(attrs = 0)
@attrs = attrs
end
def to_i
@attrs
end
end
可以这样使用:
class FileAttributes < Enum
enum_attr :readonly, 0x0001
enum_attr :hidden, 0x0002
enum_attr :system, 0x0004
enum_attr :directory, 0x0010
enum_attr :archive, 0x0020
enum_attr :in_rom, 0x0040
enum_attr :normal, 0x0080
enum_attr :temporary, 0x0100
enum_attr :sparse, 0x0200
enum_attr :reparse_point, 0x0400
enum_attr :compressed, 0x0800
enum_attr :rom_module, 0x2000
end
例子:
>> example = FileAttributes.new(3)
=> #<FileAttributes:0x629d90 @attrs=3>
>> example.readonly?
=> true
>> example.hidden?
=> true
>> example.system?
=> false
>> example.system = true
=> true
>> example.system?
=> true
>> example.to_i
=> 7
这在数据库场景中很好,或者在处理C风格的常量/枚举时(就像使用FFI时一样,RAPI广泛使用FFI)。
此外,您不必像使用散列类型解决方案那样,担心拼写错误会导致无声失败。
另一种解决方案是使用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 {
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精神。
符号的表现也很好。例如,比较两个相等的符号要比比较两个字符串快得多。
符号是红宝石之道。然而,有时我们需要与一些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类
推荐文章
- 是否可以在MiniTest中运行单个测试?
- 如何在Ruby中生成a和b之间的随机数?
- 我可以在Java中设置enum起始值吗?
- 无法安装gem -未能建立gem本地扩展-无法加载这样的文件——mkmf (LoadError)
- 如何在Ruby中创建文件
- 什么是Ruby文件。开放模式和选项?
- Ruby数组到字符串的转换
- 如何分割(块)一个Ruby数组成X元素的部分?
- Ruby中“or”和||的区别?
- c# vs Java Enum(适合c#新手)
- 如何测试参数是否存在在轨道
- 在Ruby中不创建新字符串而修饰字符串的规范方法是什么?
- RVM不是一个函数,用' RVM use…’不会起作用
- 了解Gemfile。锁文件
- 如何确定一个数组是否包含另一个数组的所有元素