Ruby Build an Address Book in Ruby Class Design Phone Number Class

Ben Flores
Ben Flores
17,074 Points

Can someone explain why we don't need the @ symbol for instance variables in our code outside of the initialize method?

I know we use the @ symbol to indicate that a variable is an instance variable. We do this inside of our initialize method.

I'm following along the videos however and noticed that Jason was able to do this:

class Contact
  attr_writer :first_name, :middle_name, :last_name
  attr_reader :phone_numbers

  def initialize
      @phone_numbers = []
  end

  def last_first
      last_first = last_name
      last_first += ", "
      last_first += first_name
      if !@middle_name.nil?
        last_first += " "
        last_first += middle_name.slice(0,1)
        last_first += "."
      end
      last_first
  end

  def print_phone_numbers
      puts "Phone Numbers"
      phone_numbers.each {|phone_number| puts phone_number}
  end
end

Our initialize method has instance variable @phone_numbers, which is an empty array. In our print_phone_numbers method, he loops through the array but phone_numbers doesn't have the @ symbol in front.

My question: Why is that the case? Is the @ symbol just not needed after the initialize method? From my understanding an instance variable can be used throughout the entire class it belongs to, so is that why we don't need the @ symbol?

This is confusing to me because in our last_first method, he does use the @ symbol when referring to @middle_name in the if statement. @middle_name was not in the initialize method.. is that why the @ symbol is needed in this case?

I might be digging into instance variables a bit much. Hope someone can help clarify!

Thanks!

kminevskiy
kminevskiy
3,101 Points

Hello Benjamin!

We don't have to use an "@" symbol because we define our attribute accessors (getters and setters) on lines 2 and 3 (after the "class" keyword). It's a shorthand for defining each getter and setter manually like this:

Getters (attribute readers):

def last_name=
    @last_name
end

def first_name
    @first_name
end

Setters (attribute writers):

def last_name=(new_lname)
    @last_name = new_lname
end

def first_name=(new_fname)
    @first_name = new_fname
end

So the way they were written in the video is just a convenience way (and the one you will see very often in the wild) of writing methods that you use to get and set your class states.

1 Answer

Oliver Duncan
Oliver Duncan
16,639 Points

@kmineskiy is right. Assuming that you meant to have an attr_reader on @first_name and @last_name instead of attr_writer, there's a huge difference between @first_name and first_name. The first is the instance variable that you have defined in your class. The second is the getter method, written automatically by attr_reader :first_name, that returns that variable. When you use first_name without an @, you're calling a method that returns that instance variable. By contrast, @middle_name doesn't have an attr_reader, and therefore no getter method. If you try to call the method middle_name, you will get an NoMethod exception.

Ben Flores
Ben Flores
17,074 Points

Thanks Oliver Duncan & kminevskiy ! He briefly explains this as well in the next video or two :P