attr_accessor :var
attr_reader :var
attr_writer :var
如果我可以使用 attr_accessor
,为什么还要选择 attr_reader
或者 attr_writer
? 是否有像性能这样的原因(我觉得不太可能)? 我猜一定是有其原因的,否则就不会有这样的关键字。
attr_accessor :var
attr_reader :var
attr_writer :var
如果我可以使用 attr_accessor
,为什么还要选择 attr_reader
或者 attr_writer
? 是否有像性能这样的原因(我觉得不太可能)? 我猜一定是有其原因的,否则就不会有这样的关键字。
您可以使用不同的访问器来传达您编写代码时的意图,并使编写类变得更加容易,无论如何调用其公共API,它都能正常工作。
class Person
attr_accessor :age
...
end
在这里,我可以看到我既可以读取年龄也可以写入年龄。
class Person
attr_reader :age
...
end
在这里,我只能读取年龄。假设它是通过该类的构造函数设置并保持不变的。如果存在一个用于年龄的更改器(writer),并且类被编写为假定年龄一旦设置就不会改变,那么调用该更改器的代码可能会导致错误。
但是背后到底发生了什么?
如果您编写:
attr_writer :age
那将被翻译成:
def age=(value)
@age = value
end
如果你写:
attr_reader :age
那会被翻译成:
def age
@age
end
如果你写:
attr_accessor :age
这会被翻译成:
def age=(value)
@age = value
end
def age
@age
end
了解了这一点,这是另一种思考方式:如果没有attr_...帮助器,并且必须自己编写访问器,您会编写比类所需更多的访问器吗?例如,如果age只需要被读取,您是否还会编写允许它被写入的方法?
attr_reader :a
与 def a; return a; end
相比,前者有明显的性能优势。视频链接:http://confreaks.net/videos/427-rubyconf2010-zomg-why-is-this-code-so-slow - Nitrodistattr_reader
定义的访问器所占用的时间是手动定义的访问器的86%。对于Ruby 1.9.0版本,使用attr_reader
定义的访问器所占用的时间是手动定义的访问器的94%。无论如何,在我的所有测试中,访问器都很快:一个访问器大约需要820纳秒(Ruby 1.8.7)或440纳秒(Ruby 1.9)。在这些速度下,您需要调用数亿次访问器才能使attr_accessor
的性能优势提高1秒以上的运行时间。 - Wayne Conradattr_accessor :a, :b
。 - Andrew_1510attr_*
比 getter 和 setter 更快。 - molli重要的是要明白,访问器限制对变量的访问,但不限制它们的内容。在Ruby中,就像在其他一些面向对象语言中一样,每个变量都是指向实例的指针。因此,如果您有一个指向哈希表的属性,并将其设置为“只读”,则始终可以更改其内容,但不能更改指针的内容。 看这个例子:
> class A
> attr_reader :a
> def initialize
> @a = {a:1, b:2}
> end
> end
=> :initialize
> a = A.new
=> #<A:0x007ffc5a10fe88 @a={:a=>1, :b=>2}>
> a.a
=> {:a=>1, :b=>2}
> a.a.delete(:b)
=> 2
> a.a
=> {:a=>1}
> a.a = {}
NoMethodError: undefined method `a=' for #<A:0x007ffc5a10fe88 @a={:a=>1}>
from (irb):34
from /usr/local/bin/irb:11:in `<main>'
正如您所看到的,可以从哈希表@a中删除键/值对,添加新键,更改值等。但是无法指向新对象,因为它是只读实例变量。
attr_reader:container
,但是没有提供编写器是有道理的,因为仅当物品被放置在新位置时,其容器才会更改,这也需要位置信息。您并不总是希望类外部完全访问实例变量。有很多情况下,允许读取实例变量是有意义的,但可能不允许写入它(例如从只读源检索数据的模型)。当然也有相反的情况,但我暂时想不到任何不牵强附会的例子。