1

Well, I can do this:

class Person
  attr_accessor :name

  def greeting
    "Hello #{@name}"
  end
end

p = Person.new
p.name = 'Dave'
p.greeting  # "Hello Dave"

but when I decide to assign the property in the class itself it doesnt work:

class Person
  attr_accessor :name
  @name = "Dave"    
  def greeting
    "Hello #{@name}"
  end
end

p = Person.new
p.greeting  # "Hello"
user2128702
  • 2,059
  • 2
  • 29
  • 74

2 Answers2

2

This is the default behavior, albeit a confusing one (especially if you're used to other languages in the OOP region).

Instance variables in Ruby starts being available when it is assigned to and normally this happens in the initialize method of your class.

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

In your examples you're using attr_accessor, this magical method produces a getter and a setter for the property name. A Person#name and Person#name=, method is created which overrides your "inline" instance variable (that's why your first example works and the second one doesn't).

So the proper way to write your expected behaviour would be with the use of a initialize method.

class Person
   def initialize(name)
     @name = name
   end
   def greeting
     "Hello, #{@name}"
   end
end

Edit

After a bit of searching I found this awesome answer, all rep should go to that question.

Community
  • 1
  • 1
Henrik Andersson
  • 45,354
  • 16
  • 98
  • 92
0

Think of a Person class as a blueprint that you can create single person instances with. As not all of these person instances will have the name "Dave", you should set this name on the instance itself.

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

  def greeting
    "Hello #{@name}"
  end
end

david = Person.new("David")
p david.greeting
# => "Hello David"

mike = Person.new("Mike")
p mike.greeting
# => "Hello Mike"
Thomas Klemm
  • 10,678
  • 1
  • 51
  • 54