In many OO languages you have a single table shared between the object's methods and the object's properties. In Ruby, all the object's consumer should be concerned with are the object's methods. If you have this in JS:
Tank:
weight: 123
moveForward: function()...
in Ruby you would have:
Tank:
ivars:
@weight = 123
methods:
weight: return @weight
move_forward...
The reason for having two distinct tables is allowing the object to decide how to store data and whether to store it, instead of having it's properties poked from outside. This allows for one extremely important advantage: UAP is maintained. That is, from the outside you work with the object's methods (sending it messages) regardless of whether those are properties or methods.
It is a wonderful feature that many other object-oriented languages either disregard in the name of optimisation (avoid indirection) or by negligence/ignorance (python is a prime example). I've written a little article on the subject here: http://live.julik.nl/2012/08/messages-versus-slots
To answer the last part of your question:
Why do we need to set up reader and writer in the Class instead of the following code and save a few lines?
To prevent situations that you have all the time in JavaScript where you address a method or a property on an object only to find undefined
in it's place, which will blow up your application many lines (or executio seconds) out of where you access the property.
In Ruby you will get an exception if you do, and it will save you from yourself thousands of times, trust me. As a matter of fact, you can create an object that will accept any getter/setter messages, and such object already exists - it's an OpenStruct. It's use normally not a good practice because of speed concerns.
[1] pry(main)> require 'ostruct'
=> true
[2] pry(main)> s = OpenStruct.new
=> #<OpenStruct>
[3] pry(main)> s.foo = 1
=> 1
[4] pry(main)> s.bar = 2
=> 2
[5] pry(main)> s.foo
=> 1
[6] pry(main)> s.bar
=> 2
[7] pry(main)> s.x
=> nil
An additional benefit from using the attribute method generators is that most Ruby documentation engines (both RDoc and YARD) will look for those to document your object methods quicker.
attr_accessor :a
creates "getter" and "setter" methods for the instance variable@a
:def a; @a; end
anddef a=(other); a=other; end
, saving you the trouble of doing so. – Cary Swoveland