Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby中的高级类Java枚举_Java_Ruby_Enums - Fatal编程技术网

Ruby中的高级类Java枚举

Ruby中的高级类Java枚举,java,ruby,enums,Java,Ruby,Enums,首先,这不是一个复制品:) 这个问题的公认答案表明,这是用Ruby表示枚举的一种好方法: class Foo BAR = 1 BAZ = 2 BIZ = 4 end 在Java中,可以将多个值和方法附加到一个枚举值。我想在Ruby中获得相同或类似的东西 表示此Java枚举的最类似Ruby的方式是什么: public enum Enum VALUE_1("Value 1"), VALUE_2("Value 2"), VALUE_3("Value 3");

首先,这不是一个复制品:)

这个问题的公认答案表明,这是用Ruby表示枚举的一种好方法:

class Foo
  BAR = 1
  BAZ = 2
  BIZ = 4
end
在Java中,可以将多个值和方法附加到一个枚举值。我想在Ruby中获得相同或类似的东西

表示此Java枚举的最类似Ruby的方式是什么:

public enum Enum

    VALUE_1("Value 1"),
    VALUE_2("Value 2"),
    VALUE_3("Value 3");

    Enum(String value) {
        this.value = value;
    }
    public String getValue() {
        return value;
    }
    private String value;
}  
编辑:

我还想保留Java枚举的隐式特性:

  • 。。。检索序数值
  • 。。。对枚举值(或等效值)调用方法
示例:

Enum.VALUE_1.getValue(); // "Value 1"
Enum.VALUE_2.name();     // "VALUE_2"
Enum.VALUE_3.ordinal();  // 2

您始终可以创建类似Java版本的系统:

module Foo
  class Value
    attr_reader :value

    def initialize(value)
      # Save a frozen, immutable copy
      @value = value.dup.freeze
    end

    # Patch in methods to make it appear more friendly and string-like
    alias_method :to_s, :value
    alias_method :inspect, :value
  end

  # Define constants
  BAR = Value.new('bar')
  BAZ = Value.new('baz')
  BIZ = Value.new('biz')
end

puts Foo::BAR
# => bar

这是我建议的代码

枚举模块.rb

module EnumModule
  CONVERT_PROC = Proc.new do
    @values = constants.collect{|c| const_get(c)}.freeze

    @values.each_with_index do |value, idx|
      the_symbol = constants.find{|c| const_get(c) == value}
      sig = class << value ; self end
      sig.send :define_method, :name, proc{the_symbol}
      sig.send :define_method, :ordinal, proc{idx}

      if value.is_a? Hash
        value.each do |k, v|
          sig.send :define_method, k, (v.is_a?(Proc) ? v : proc{v})
        end
      end
      value.freeze
    end

    class << self
      alias :value_of :const_get
    end

    module_function
    def each
      @values.each { |v| yield v }
    end
    def values
      @values
    end
    extend Enumerable

    freeze
  end

  def self.extended extending_obj
    extending_obj.module_eval &CONVERT_PROC
  end
end
require 'EnumModule'

module SampleEnum
  VALUE_1 = {
    to_s: 'Value_1_str',
    get_value: proc{'Value 1'}
  }

  VALUE_2 = {
    to_s: 'Value_2_str',
    get_value: proc{'Value 2'}
  }

  extend EnumModule
end

#defined method
p SampleEnum::VALUE_1.get_value #=> "Value 1"
p SampleEnum::VALUE_2.get_value #=> "Value 2"

p SampleEnum::VALUE_1.to_s      #=> "Value_1_str"

#name (returns the symbol of the constant)
p SampleEnum::VALUE_1.name #=> :VALUE_1
p SampleEnum::VALUE_2.name #=> :VALUE_2

#ordinal
p SampleEnum::VALUE_1.ordinal #=> 0
p SampleEnum::VALUE_2.ordinal #=> 1

#emulates Java Enum's valueOf(is an alias of const_get)
p SampleEnum.value_of('VALUE_1').get_value  #=> "Value 1"
p SampleEnum.value_of(:VALUE_1).get_value  #=> "Value 1"
p SampleEnum.const_get('VALUE_1').get_value  #=> "Value 1"

#emulates Java Enum's values
SampleEnum.values.each do |m|
  p m.ordinal, m.name, m.get_value, m.to_s
end

#an Enumerable
p SampleEnum.map{|m| m.get_value} #=> ["Value 1","Value 2"]

通过扩展
EnumModule
Hash
constants'内容(键和值)成为单例方法。

您应该删除构造函数上的“public”修饰符以使其可编译。根据需要的行为,将其替换为
attr\u reader
可能有意义。然而,我不明白为什么要完全删除它,因为我希望人们至少希望能够读取值,否则首先就没有必要拥有值。绝对正确,至少他应该能够做到:MyEnum::VALUE2.value,或者我们可以覆盖到_s以返回值,这将更简洁;)在那个例子中,我将如何检索序号值(在Java:VALUE1.ordinal()中),而您不会这样做。为此,您必须将数字另存为第二个值,或者编写一个自动保存索引的解决方案。更新了我的问题,使其更加精确。
module EnumModule
  CONVERT_PROC = Proc.new do
    @values = constants.collect{|c| const_get(c)}.freeze

    @values.each_with_index do |value, idx|
      the_symbol = constants.find{|c| const_get(c) == value}
      sig = class << value ; self end
      sig.send :define_method, :name, proc{the_symbol}
      sig.send :define_method, :ordinal, proc{idx}

      if value.is_a? Hash
        value.each do |k, v|
          sig.send :define_method, k, (v.is_a?(Proc) ? v : proc{v})
        end
      end
      value.freeze
    end

    class << self
      alias :value_of :const_get
    end

    module_function
    def each
      @values.each { |v| yield v }
    end
    def values
      @values
    end
    extend Enumerable

    freeze
  end

  def self.extended extending_obj
    extending_obj.module_eval &CONVERT_PROC
  end
end
require 'EnumModule'

module SampleEnum
  VALUE_1 = {
    to_s: 'Value_1_str',
    get_value: proc{'Value 1'}
  }

  VALUE_2 = {
    to_s: 'Value_2_str',
    get_value: proc{'Value 2'}
  }

  extend EnumModule
end

#defined method
p SampleEnum::VALUE_1.get_value #=> "Value 1"
p SampleEnum::VALUE_2.get_value #=> "Value 2"

p SampleEnum::VALUE_1.to_s      #=> "Value_1_str"

#name (returns the symbol of the constant)
p SampleEnum::VALUE_1.name #=> :VALUE_1
p SampleEnum::VALUE_2.name #=> :VALUE_2

#ordinal
p SampleEnum::VALUE_1.ordinal #=> 0
p SampleEnum::VALUE_2.ordinal #=> 1

#emulates Java Enum's valueOf(is an alias of const_get)
p SampleEnum.value_of('VALUE_1').get_value  #=> "Value 1"
p SampleEnum.value_of(:VALUE_1).get_value  #=> "Value 1"
p SampleEnum.const_get('VALUE_1').get_value  #=> "Value 1"

#emulates Java Enum's values
SampleEnum.values.each do |m|
  p m.ordinal, m.name, m.get_value, m.to_s
end

#an Enumerable
p SampleEnum.map{|m| m.get_value} #=> ["Value 1","Value 2"]