如何在 Ruby 中使用 C# 风格的枚举?

发布于 2024-07-07 04:46:51 字数 37 浏览 10 评论 0原文

我只是想知道在 Ruby 中模拟 C# 风格枚举的最佳方法。

I just want to know the best way to emulate a C# style enumeration in Ruby.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

冰雪梦之恋 2024-07-14 04:46:51

具体来说,我希望能够针对给定某些变量的值集执行逻辑测试。 例如窗口的状态:“最小化、最大化、关闭、打开”

如果您需要枚举映射到值(例如,您需要最小化等于 0,最大化等于 100 等),我会使用哈希符号到值,就像这样:

WINDOW_STATES = { :minimized => 0, :maximized => 100 }.freeze

冻结(就像内特所说)可以防止你将来意外破坏东西。
您可以通过这样做来检查某些内容是否有效

WINDOW_STATES.keys.include?(window_state)

或者,如果您不需要任何值,而只需要检查“成员资格”,那么数组就可以了

WINDOW_STATES = [:minimized, :maximized].freeze

像这样使用它

WINDOW_STATES.include?(window_state)

如果您的键将是字符串(例如RoR 应用程序中的“状态”字段),那么您可以使用字符串数组。 我在许多 Rails 应用程序中一直这样做。

WINDOW_STATES = %w(minimized maximized open closed).freeze

这几乎就是 Rails validates_inclusion_of 验证器的目的:-)

个人注意:

我不喜欢输入 include? 一直如此,所以我有这个(只是因为 .in?(1, 2, 3) 的情况而变得复杂:

class Object

    # Lets us write array.include?(x) the other way round
    # Also accepts multiple args, so we can do 2.in?( 1,2,3 ) without bothering with arrays
    def in?( *args )
        # if we have 1 arg, and it is a collection, act as if it were passed as a single value, UNLESS we are an array ourselves.
        # The mismatch between checking for respond_to on the args vs checking for self.kind_of?Array is deliberate, otherwise
        # arrays of strings break and ranges don't work right
        args.length == 1 && args.first.respond_to?(:include?) && !self.kind_of?(Array) ?
            args.first.include?( self ) :
            args.include?( self )
        end
    end
end

这让你可以输入

window_state.in? WINDOW_STATES

Specifically, I would like to be able to perform logical tests against the set of values given some variable. Example would be the state of a window: "minimized, maximized, closed, open"

If you need the enumerations to map to values (eg, you need minimized to equal 0, maximised to equal 100, etc) I'd use a hash of symbols to values, like this:

WINDOW_STATES = { :minimized => 0, :maximized => 100 }.freeze

The freeze (like nate says) stops you from breaking things in future by accident.
You can check if something is valid by doing this

WINDOW_STATES.keys.include?(window_state)

Alternatively, if you don't need any values, and just need to check 'membership' then an array is fine

WINDOW_STATES = [:minimized, :maximized].freeze

Use it like this

WINDOW_STATES.include?(window_state)

If your keys are going to be strings (like for example a 'state' field in a RoR app), then you can use an array of strings. I do this ALL THE TIME in many of our rails apps.

WINDOW_STATES = %w(minimized maximized open closed).freeze

This is pretty much what rails validates_inclusion_of validator is purpose built for :-)

Personal Note:

I don't like typing include? all the time, so I have this (it's only complicated because of the .in?(1, 2, 3) case:

class Object

    # Lets us write array.include?(x) the other way round
    # Also accepts multiple args, so we can do 2.in?( 1,2,3 ) without bothering with arrays
    def in?( *args )
        # if we have 1 arg, and it is a collection, act as if it were passed as a single value, UNLESS we are an array ourselves.
        # The mismatch between checking for respond_to on the args vs checking for self.kind_of?Array is deliberate, otherwise
        # arrays of strings break and ranges don't work right
        args.length == 1 && args.first.respond_to?(:include?) && !self.kind_of?(Array) ?
            args.first.include?( self ) :
            args.include?( self )
        end
    end
end

This lets you type

window_state.in? WINDOW_STATES
懷念過去 2024-07-14 04:46:51

它并不完全相同,但我经常会为这种事情构建一个散列:

STATES = {:open => 1, :closed => 2, :max => 3, :min => 4}.freeze()

冻结散列可以防止我意外修改其内容。

此外,如果您想在访问不存在的内容时引发错误,可以使用默认 Proc 来执行此操作:

STATES = Hash.new { |hash, key| raise NameError, "#{key} is not allowed" }
STATES.merge!({:open => 1, :closed => 2, :max => 3, :min => 4}).freeze()

STATES[:other] # raises NameError

It's not quite the same, but I'll often build a hash for this kind of thing:

STATES = {:open => 1, :closed => 2, :max => 3, :min => 4}.freeze()

Freezing the hash keeps me from accidentally modifying its contents.

Moreover, if you want to raise an error when accessing something that doesn't exist, you can use a defualt Proc to do this:

STATES = Hash.new { |hash, key| raise NameError, "#{key} is not allowed" }
STATES.merge!({:open => 1, :closed => 2, :max => 3, :min => 4}).freeze()

STATES[:other] # raises NameError
野心澎湃 2024-07-14 04:46:51

我不认为 Ruby 支持真正的枚举——不过,仍然有可用的解决方案。

枚举和 Ruby

I don't think Ruby supports true enums -- though, there are still solutions available.

Enumerations and Ruby

煞人兵器 2024-07-14 04:46:51

在 ruby​​ 中定义 Enum 的最简单方法是使用带有常量变量的类。

class WindowState
  Open = 1
  Closed = 2
  Max = 3
  Min = 4
end

The easiest way to define an Enum in ruby to use a class with constant variables.

class WindowState
  Open = 1
  Closed = 2
  Max = 3
  Min = 4
end
べ繥欢鉨o。 2024-07-14 04:46:51

正如其他人所说,创建一个类或散列是可行的。 然而,Ruby 要做的是使用 符号。 Ruby 中的符号以冒号开头,如下所示:

greetingtype = :hello

它们有点像仅由名称组成的对象。

Making a class or hash as others have said will work. However, the Ruby thing to do is to use symbols. Symbols in Ruby start with a colon and look like this:

greetingtype = :hello

They are kind of like objects that consist only of a name.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文