Why use Ruby's attr
Ruby has this handy and convenient way to share instance variables by using keys like
attr_accessor :var
attr_reader :var
attr_writer :var
Why would I choose attr_reader
or attr_writer
if I could simply use attr_accessor
? Is there something like performance (which I doubt)? I guess there is a reason, otherwise they wouldn't have made such keys.
You may use the different accessors to communicate your intent to someone reading your code, and make it easier to write classes which will work correctly no matter how their public API is called.
class Person
attr_accessor :age
...
end
Here, I can see that I may both read and write the age.
class Person
attr_reader :age
...
end
Here, I can see that I may only read the age. Imagine that it is set by the constructor of this class and after that remains constant. If there were a mutator (writer) for age and the class were written assuming that age, once set, does not change, then a bug could result from code calling that mutator.
But what is happening behind the scenes?
If you write:
attr_writer :age
That gets translated into:
def age=(value)
@age = value
end
If you write:
attr_reader :age
That gets translated into:
def age
@age
end
If you write:
attr_accessor :age
That gets translated into:
def age=(value)
@age = value
end
def age
@age
end
Knowing that, here's another way to think about it: If you did not have the attr_... helpers, and had to write the accessors yourself, would you write any more accessors than your class needed? For example, if age only needed to be read, would you also write a method allowing it to be written?
All of the answers above are correct; attr_reader
and attr_writer
are more convenient to write than manually typing the methods they are shorthands for. Apart from that they offer much better performance than writing the method definition yourself. For more info see slide 152 onwards from this talk (PDF) by Aaron Patterson.
Not all attributes of an object are meant to be directly set from outside the class. Having writers for all your instance variables is generally a sign of weak encapsulation and a warning that you're introducing too much coupling between your classes.
As a practical example: I wrote a design program where you put items inside containers. The item had attr_reader :container
, but it didn't make sense to offer a writer, since the only time the item's container should change is when it's placed in a new one, which also requires positioning information.
上一篇: 根据名称获取实例变量的值
下一篇: 为什么要使用Ruby的属性