是否可以在Struct
实例中动态创建属性?
class Person < Struct.new(:name)
end
p = Person.new("Bilbo")
p[:surname] = "Jenkins" # does not work
答案 0 :(得分:1)
您可以使用OpenStruct
:
require 'ostruct'
p = OpenStruct.new(name: "Bilbo")
p[:surname] = "Jenkins"
p.surname # => "Jenkins"
答案 1 :(得分:1)
您可以通过以下方式在Person
课程中定义新方法:
Person.send(:define_method, :surname){@surname}
Person.send(:define_method, :surname=){|x|@surname=x}
我更喜欢define_method
而不是instance_eval
,因为我尽可能省略eval
。
答案 2 :(得分:0)
您可以继承Struct
,在这种情况下,您将创建两个类,但更常见的是创建一个类:
Person = Struct.new(:name)
Person.instance_methods(false)
#=> [:name, :name=]
p = Person.new("Bilbo")
#=> #<struct Person name="Bilbo">
Does `p` have an instance variable `@name` whose value is `"Bilbo"`?
p.instance_variables
#=> []
不,它没有。相反,它有&#34;成员&#34;:
p.members
#=> [:name]
可以将name
视为具有Struct
提供的访问者的实例变量吗?
p.name
#=> "Bilbo"
p.name = "cat"
p.name
#=> "cat"
是的!这是因为Struct
实例的成员存储在您不打算直接访问的数组中,只能通过访问者访问。
我们可以动态添加Struct
个成员吗?我不知道答案,但不提供方法来轻松完成。相反,只需添加实例变量和(可选)访问器。
我们可以添加一个实例变量并将其值设置为:
p.instance_variable_set('@surname', 'Jenkins')
#=> "Jenkins"
p.instance_variables
#=> [:@surname]
并使用以下命令检索其值:
p.instance_variable_get('@surname')
#=> "Jenkins"
如果您希望为该变量创建访问器,这是一种方式:
p.class.instance_eval do
attr_accessor :surname
end
p.surname
#=> "Jenkins"
p.surname = 'cat'
#=> "cat"
p.surname
#=> "cat"
p.class.instance_methods(false)
#=> [:name, :name=, :surname, :surname=]