【发布时间】:2020-01-03 16:51:15
【问题描述】:
我创建了一个对象,我希望根据一些条件检查向该对象添加一些属性。我怎样才能做到这一点? 解释我想要什么:
A=Object.new
if(something happens)
{
#make A have another attibute say age
#& store something in A.age
}
【问题讨论】:
标签: ruby
我创建了一个对象,我希望根据一些条件检查向该对象添加一些属性。我怎样才能做到这一点? 解释我想要什么:
A=Object.new
if(something happens)
{
#make A have another attibute say age
#& store something in A.age
}
【问题讨论】:
标签: ruby
首先,关于 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
【讨论】:
a = Object.new 和A = Object.new 做了太多不同的事情(第一个定义一个局部变量,另一个定义一个全局常量)。
您可以使用 OpenStruct:
a = OpenStruct.new
if condition
a.age = 4
end
或者只使用普通的旧哈希。
【讨论】:
这只会将属性添加到对象:
a = Object.new
if (something happens)
class << a
attr_accessor :age
end
a.age = new_age_value
end
【讨论】:
如果在编写代码时该属性的名称是已知的,那么您可以执行已经建议的操作:
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
【讨论】:
a.singleton_class.send(:attr_accessor, attr_name)。谢谢!
您可以使用instance_variable_set 在 Object 类的实例上设置变量(并使用instance_variable_get 获取它。)Object 类没有任何可以直接设置的属性。
但是,我怀疑这不是您想要实现的最佳解决方案;直接使用 Object 类不是规范,而是定义或使用从它继承的具有您想要使用的属性的类。
【讨论】:
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
【讨论】: