Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intermingling attr_accessor and an initialize method in one class

I see code like:

class Person
  def initialize(name)
    @name = name
  end
end

I understand this allows me to do things like person = Person.new and to use @name elsewhere in my class like other methods. Then, I saw code like:

class Person
  attr_accessor :name
end

...

person = Person.new
person.name = "David"

I'm just at a loss with these two methods mesh. What are the particular uses of def initialize(name)? I suppose attr_accessor allows me to read and write. That implies they are two separate methods. Yes? Want clarifications on def initialize and attr_accessor and how they mesh.

like image 436
David Avatar asked May 20 '13 18:05

David


2 Answers

initialize and attr_accessor have nothing to do with each other. attr_accessor :name creates a couple of methods:

def name
  @name
end

def name=(val)
  @name = val
end

If you want to set name upon object creation, you can do it in the initializer:

def initialize(name)
  @name = name
  # or
  # self.name = name
end

But you don't have to do that. You can set name later, after creation.

p = Person.new
p.name = "David"
puts p.name # >> "David"
like image 64
Sergio Tulentsev Avatar answered Oct 12 '22 14:10

Sergio Tulentsev


Here is the answer you are looking for Classes and methods. Read it carefully.

Here is a good documentation from the link:

Classes and methods

Now we are ready to create our very own Address class. Let's start simple. Let's start with an address that only contains the "street" field.

This is how you define a class:

class Address
    def initialize(street)  
        @street = street 
    end
end
                   

Let's go through this:

  • The class keyword defines a class.

  • By defining a method inside this class, we are associating it with this class.

  • The initialize method is what actually constructs the data structure. Every class must contain an initialize method.

@street is an object variable. Similar to the keys of a hash. The @ sign distinguishes @street as an object variable. Every time you create an object of the class Address, this object will contain a @street variable.

Let's use this class to create an address object.

address = Addres.new("23 St George St.")  
                   

That's it. address is now an object of the class Address Reading the data in an object

Suppose that we want to read the data in the address object. To do this, we need to write a method that returns this data:

class Address
    def initialize(street)   
        @street = street 
    end

    # Just return @street
    def street
        @street
    end
end
                   

Now the method Address#street lets you read the street of the address. In irb:

>> address.street 
=> "23 St George St."
                   

A property of an object, which is visible outside, is called an attribute. In this case, street is is an attribute. In particular, it is a readable attribute. Because this kind of attribute is very common, Ruby offers you a shortcut through the attr_reader keyword:

class Address
    attr_reader :street
    def initialize(street)   
        @street = street 
    end
end

                   

Changing the data in an object

We can also define a method to change the data in an object.

class Address
    attr_reader :street
    def initialize(street)  
        @street = street 
    end
    def street=(street)
        @street = street
    end
end

                   

Ruby is pretty smart in its use of the street= method:

address.street = "45 Main St."
                   

Notice that you can put spaces betten street and =. Now that we can change the address data, we can simplify the initialize method, and have it simply default the street to the empty string "".

class Address
    attr_reader :street
    def initialize
        @street = ""
    end
    def street=(street)
        @street = street  
    end
end

address = Address.new
address.street = "23 St George St."


                   

This might not seem like much of a simplification, but when we add the city, state and zip fields, and more methods this will make the class definition a bit simpler.

Now, street is also a writable attribute. As before, you can declare it as such with attr_writer:

class Address
    attr_reader :street
    attr_writer :street  
    def initialize
        @street = ""
    end
end
                   

Accessing data

Very often, you have attributes that are both readable and writable attributes. Ruby lets you lump these together with attr_accessor. I guess these would be called "accessible attributes", but I have never seen them be called that.

class Address
    attr_accessor :street  
    def initialize
        @street = ""
    end
end

                   

With this knowledge, it is now easy to define the entire addressbook structure. As it turns out, attr_accessor and friends all accept multiple arguments.

class Address
    attr_accessor :street, :city, :state, :zip  
    def initialize
        @street = @city = @state = @zip = ""
    end
end
                   
like image 20
Arup Rakshit Avatar answered Oct 12 '22 12:10

Arup Rakshit