Attribute Readers and Writers

In fact, there is a simpler and shorter way of creating a pair of get and set accessors simultaneously. All you have to do is use two special methods, attr_reader and attr_writer, followed by a symbol (a name preceded by a colon):

attr_reader :description
attr_writer :description

You should add this code inside your class definition like this:

class Thing
   attr_reader :description
   attr_writer :description
    # maybe some more methods here...
end

Calling attr_reader with a symbol has the effect of creating a get accessor (here named description) for an instance variable (@description) with a name matching the symbol (:description).

Calling attr_writer similarly creates a set accessor for an instance variable. Instance variables are considered to be the “attributes” of an object, which is why the attr_reader and attr_writer methods are so named.

The accessors2.rb program contains some examples of attribute readers and writers in action. This is its version of the Thing class:

accessors2.rb

class Thing

     attr_reader :description
      attr_writer :description
     attr_writer :name

      def initialize( aName, aDescription )
          @name         = aName
          @description  = aDescription
      end

         # get accessor for @name
     def name
          return @name.capitalize
      end

end

Here the Thing class explicitly defines a get method accessor for the @name attribute. The advantage of writing a complete method like this is that it gives you the opportunity to do some extra processing rather than simply reading and writing an attribute value. The get accessor, name , uses the String.capitalize method to return the string value of @name with its initial letter in uppercase.

When assigning a value to the @name attribute, I don’t need to do any special processing, so I have given it an attribute writer instead of a set accessor method .

The @description attribute needs no special processing at all, so I use attr_reader and attr_writer instead of accessor methods in order to get and set the value of the @description variable .

Note

Are they attributes or properties? Don’t be confused by the terminology. In Ruby, an attribute is the equivalent of what many programming languages call a property.

When you want both to read and to write a variable, the attr_accessor method provides a shorter alternative than using both attr_reader and attr_writer. I have used this to access the value attribute in the Treasure class:

attr_accessor :value

This is equivalent to the following:

attr_reader :value
attr_writer :value

Earlier I said that calling attr_reader with a symbol actually creates a variable with the same name as the symbol. The attr_accessor method also does this.

In the code for the Thing class, this behavior is not obvious since the class has an initialize method that explicitly creates the variables. The Treasure class, however, makes no reference to the @value variable in its initialize method:

class Treasure < Thing
    attr_accessor :value

    def initialize( aName, aDescription )
        super( aName, aDescription )
    end
end

The only indication that @value exists at all is this accessor definition:

attr_accessor :value

My code at the bottom of the accessors2.rb source file sets the value of each Treasure object as a separate operation, following the creation of the object itself, like this:

t1.value = 800

Even though it has never been formally declared, the @value variable really does exist, and you are able to retrieve its numerical value using the get accessor: t1.value. To be absolutely certain that the attribute accessor really has created @value, you can always look inside the object using the inspect method. I have done so in the final two code lines in this program:

puts "This is treasure1: #{t1.inspect}"
puts "This is treasure2: #{t2.inspect}"

This displays the data inside the t1 and t2 objects, including the @value variables:

This is treasure1: #<Treasure:0x33a6c88 @value=100, @name="sword",
 @description="an Elvish weapon forged of gold (now somewhat tarnished)">
This is treasure2: #<Treasure:0x33a6c4c @value=500, @name="dragon horde",
 @description="a huge pile of jewels">

Attribute accessors can initialize more than one attribute at a time if you send them a list of symbols separated by commas, like this:

accessors3.rb

attr_reader :name, :description
attr_writer(:name, :description)
attr_accessor(:value, :id, :owner)

As always, parentheses around the arguments are optional but, in my view (for reasons of clarity), are to be preferred.

Now let’s see how to put attribute readers and writers to use in my adventure game. Load the 2adventure.rb program. You will see that I have created two readable attributes in the Thing class: name and description. I have also made description writeable; however, because I don’t plan to change the names of any Thing objects, the name attribute is not writeable:

2adventure.rb

attr_reader( :name, :description )
attr_writer( :description )

I have created a method called to_s, which returns a string describing the Treasure object. Recall that all Ruby classes have a to_s method as standard. The Thing.to_s method overrides (and replaces) the default one.

def to_s # override default to_s method
    return "(Thing.to_s):: The #{@name} Thing is #{@description}"
end

You can override existing methods when you want to implement new behavior appropriate to the specific class type.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.144.229