1

我正在阅读另一个 SO question Enums in Ruby,它有以下代码片段:

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

据我了解,这是定义一个名为的类方法enum_attr,对吗?我不确定的是在方法中包含define_method语句意味着什么enum_attr

然后稍后在那篇文章中,它显示了该类的扩展如下

class FileAttributes < Enum
  enum_attr :readonly,       0x0001
  enum_attr :hidden,         0x0002
end

我不太明白第二部分是做什么的——有人能解释一下吗?

4

2 回答 2

2

Enum中,方法 ,enum_attr定义在类的单例上,可用于所有子类。此方法在类定义主体的范围内,并在FileAttributes其中使用参数调用:readonly, 0x0001then :hidden, 0x0002

enum_attr被调用时(让我们只看第一个调用,enum_attr :readonly, 0x0001),它定义了两个方法:readonly?& readonly=(set)。此调用的结果在enum_attr功能上等同于在 中写出以下内容FileAttributes

def readonly?
  @attrs & 0x0001 != 0
end

def readonly=(set)
  if set
    @attrs |= 0x0001
  else
    @attrs &= ~0x0001
  end
end

由于传递给的块是一个闭包,因此当您调用定义的方法时,传递块的作用域中define_method的变量仍然在作用域内。num换句话说,num传入的变量在生成的方法中enum_attr仍然可用,并且稍后从不同的范围调用它们时。readonly?readonly=

define_method必须使用,因为方法的名称是动态生成的(即,我们事先不知道方法的名称)。

于 2012-06-24T23:44:18.090 回答
1

您正在查看一个类方法,该方法生成使用位域存储的真/假属性。你有 C(或者 Java)的背景吗?如果是这样,您可能熟悉位域和一般的“位旋转”。大多数有关这些主题的 Internet 资源都与 C 相关;但您仍然可以在 Ruby 和其他语言中使用它们。

在这种情况下,您不会从将布尔属性存储在单个位中获得任何好处,我建议您不要实际使用此代码。您最好为每个属性使用不同的实例变量,带有truefalse值。

于 2012-06-24T23:52:59.633 回答