Как я могу использовать перечисления в стиле C# в Ruby?
Я просто хочу узнать, как лучше всего эмулировать перечисление в стиле C# в Ruby.
5 ответов
В частности, я хотел бы иметь возможность выполнять логические тесты с набором значений, заданных некоторой переменной. Примером может служить состояние окна: "свернуто, развернуто, закрыто, открыто"
Если вам нужны перечисления для сопоставления со значениями (например, вам нужно минимизировать до 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)
Если ваши ключи будут строками (как, например, поле 'state' в приложении RoR), то вы можете использовать массив строк. Я делаю это ВСЕ ВРЕМЯ во многих наших приложениях рельсов.
WINDOW_STATES = %w(minimized maximized open closed).freeze
Это в значительной степени то, что рельсы 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()
Замораживание хеша не дает мне случайно изменить его содержимое.
Более того, если вы хотите вызвать ошибку при доступе к чему-то, что не существует, вы можете использовать для этого процедуру по умолчанию:
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
Самый простой способ определить Enum в ruby - использовать класс с постоянными переменными.
class WindowState
Open = 1
Closed = 2
Max = 3
Min = 4
end
Я не думаю, что Ruby поддерживает истинные перечисления - хотя, есть все еще доступные решения.
Создание класса или хэша, как говорили другие, сработает. Тем не менее, Ruby должен использовать символы. Символы в Ruby начинаются с двоеточия и выглядят так:
greetingtype = :hello
Они вроде объектов, которые состоят только из имени.