动态地向Ruby对象添加属性

时间:2010-07-08 09:52:37

标签: ruby

我创建了一个对象,我想根据一些条件检查,为这个对象添加一些属性。我怎样才能做到这一点? 解释我想要的东西:

A=Object.new
if(something happens)
{
  #make A have another attibute say age
  #& store something in A.age

}

6 个答案:

答案 0 :(得分:48)

首先,关于ruby的事情是它允许使用不同的语法,ruby编码器广泛使用它。大写标识符是类或常量(感谢sepp2k的评论),但您尝试将其作为对象。并且几乎没有人使用{}标记多行块。

a = Object.new
if (something happens)
  # do something
end

我不确定你的问题是什么,但我有一个想法,这就是解决方案:

如果您知道该类可以具有哪些属性,并且它有限,则应使用

class YourClass
  attr_accessor :age
end

attr_accessor :age简称:

def age
  @age
end
def age=(new_age)
  @age = new_age
end

现在你可以这样做:

a = YourClass.new
if (some condition)
  a.age = new_value
end

如果你想完全动态地做,你可以这样做:

a = Object.new
if (some condition)
  a.class.module_eval { attr_accessor :age}
  a.age = new_age_value
end

答案 1 :(得分:21)

这会将属性仅添加到对象:

a = Object.new
if (something happens)
  class << a
    attr_accessor :age
  end
  a.age = new_age_value
end

答案 2 :(得分:20)

您可以使用OpenStruct:

a = OpenStruct.new
if condition
    a.age = 4
end

或者只使用普通的旧哈希。

答案 3 :(得分:11)

如果在代码编写时知道属性的名称,那么您可以执行已经建议的内容:

class A
end

a = A.new
a.age = 20 # Raises undefined method `age='

# Inject attribute accessors into instance of A
class << a
  attr_accessor :age
end

a.age = 20 # Succeeds
a.age # Returns 20

b = A.new
b.age # Raises undefined method, as expected, since we only modified one instance of A

但是,如果属性的名称是动态的,并且仅在运行时已知,那么您必须稍微调用attr_accessor

attr_name = 'foo'

class A
end

a = A.new
a.foo = 20 # Raises undefined method `foo='

# Inject attribute accessors into instance of A
a.instance_eval { class << self; self end }.send(:attr_accessor, attr_name)

a.foo = 20 # Succeeds
a.foo # Returns 20

答案 4 :(得分:6)

您可以使用instance_variable_set在Object类的实例上设置变量(和instance_variable_get来获取它。)Object类没有可以直接设置的任何属性。

然而,我怀疑这不是你想要实现的最佳解决方案;它不是直接使用Object类的规范,而是定义或使用从中继承的类,它们具有您想要使用的属性。

答案 5 :(得分:1)

class Person; end
person = Person.new
person.age # throws NoMethodError

if true
  person.singleton_class.module_eval { attr_accessor :age }
end

person.age = 123
person.age #=> 123

person2 = Person.new
person2.age #=> throws NoMethodError