RubyでC#スタイルの列挙を使用するにはどうすればよいですか?
-
03-07-2019 - |
質問
RubyでC#スタイルの列挙をエミュレートする最良の方法を知りたいだけです。
解決
具体的には、変数を指定して値のセットに対して論理テストを実行できるようにしたいと思います。例は、ウィンドウの状態です:「最小化、最大化、クローズ、オープン」
列挙を値にマップする必要がある場合(たとえば、最小化して0に等しく、最大化して100に等しくする必要があるなど)、次のように値のシンボルのハッシュを使用します。
WINDOW_STATES = { :minimized => 0, :maximized => 100 }.freeze
(Nateが言うように)凍結することで、偶然に物を壊すことを防ぎます。 これを行うことにより、何かが有効かどうかを確認できます
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
他のヒント
まったく同じではありませんが、この種のことのハッシュを作成することがよくあります:
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
Rubyは本当の列挙型をサポートしているとは思いませんが、解決策はまだあります。
RubyでEnumを定義して定数変数を持つクラスを使用する最も簡単な方法。
class WindowState
Open = 1
Closed = 2
Max = 3
Min = 4
end
他の人が言ったようにクラスまたはハッシュを作成しても機能します。ただし、Rubyで行うことは、シンボル。 Rubyのシンボルはコロンで始まり、次のようになります。
greetingtype = :hello
これらは、名前のみで構成される一種のオブジェクトです。