【发布时间】:2019-06-11 07:41:27
【问题描述】:
看这段代码:
class Person
attr_accessor :name, :age
def initialize(data)
data.each { |k, v| self.send("#{k}=", v) }
end
end
data = {
name: 'Luke Skywalker',
age: 19
}
person = Person.new(data)
person.inspect # => #<Person @name="Luke Skywalker", @age=19>
这很好用。它做它应该做的事情。问题是,我不希望属性是可变的,换句话说,我想使用attr_reader。我知道如果我使用attr_reader Ruby 不会为我创建编写器方法(def attr=(val) ...),因此我将无法在send 中使用"#{k}="。我真的不想这样做:
class Person
attr_reader :name, :age
def initialize(name:, age:)
@name = name
@age = age
end
end
你们知道实现我想要的任何解决方法吗?
感谢大家的帮助!
【问题讨论】:
-
并不是说它一定更好,但我想指出,除了使用 instance_variable_set ...之外,还有一种不同的方法。你可以创建一个私有的 attr_reader
-
@maxpleaner 你能详细说明一下吗?
-
attr_reader :name+private :name。但这并不意味着它是不可变的。如果您希望它们不可变,您可以执行@name = name.freeze和/或添加freeze作为initialize 方法的最后一行,那么就无法更改任何实例变量。 -
对不起,我的意思是私人 attr_writer ......但@KimmoLehto 是对的,我忘记了
private方法......你可以做attr_accessor :name; private :name=
标签: ruby