Is there any instance variable convention used in Ruby code? Namely, I noticed that, in the examples section, instance variable are initialized using the ‘@’ and then the code uses a variable name without the ‘@’:
class BookInStock
attr_reader: isbn
attr_accessor: price
def initialize (isbn, price)
@isbn = isbn
@price = Float (price)
end
def price_in_cents
Integer (price * 100 + 0.5)
end
end
And there are examples where the code, the instance variable is used all the time with the prefix ‘@’
class BookStock
def set_price (price)
@price = price
end
def get_price
@price
end
end
What is the difference these records? When should I use ‘@’ only in the initialization of an object and when in all the class methods?
You can only use the instance variable name without
@if you have defined an attribute reader for this variable (withattr_readerorattr_accessor). This is a lightweight helper to create a method that returns the instance variable’s value.The difference is a question between using the public interface of your class or accessing private data. It is recommended to use the public interface in subclasses or included modules, for example. This ensures encapsulation. So you should not access instance variables from within subclasses or modules.
In the class itself, ask yourself this question: if the implementation of the attribute changes, should my usage the attribute change as well? If the answer is yes, use the instance variable directly; if it’s no, use the public attribute.
An example. Suppose we have a
Personclass that represents a person and should contain that person’s name. First there is this version, with only a simplenameattribute:Note how we use the instance variable for the
blank?method, but the public attribute for theto_smethod. This is intentional!Let’s say that in a refactoring step we decide that the
Personclass should keep track of afirst_nameandlast_nameseperately.We now change the
nameattribute to a regular method, which composes the name from a person’s first and last name. We can now see that it is possible to keep the same implementation forto_s. However,blank?needs to be changed because it was dependent on the underlying data. This is the reason whyto_sused the attribute, butblank?used the instance variable.Of course, the distinction is not always easy to make. When in doubt, choose the public API over accessing private data.