Can Someone Explain This to Me?

class Body
@feet = 2
puts “We have #{@feet} feet”
def initialize

end
def report
puts “We have #{@feet} feet”
end
end

b=Body.new
b.report

Why is it in the above class the first puts prints correctly but the
second
puts doesn’t have a value for the instance variable?

On Wed, Aug 20, 2008 at 7:38 AM, Ron G. [email protected] wrote:

b=Body.new
b.report

Why is it in the above class the first puts prints correctly but the second
puts doesn’t have a value for the instance variable?

When you have a variable with @ in front, it’s an instance variable of
the object which
is self when the variable is created. In your case, @feet is created
when self is the class
object Body. It is not an instance variable of an object of class
Body, as it would if you
did this:

irb(main):001:0> class Body
irb(main):002:1> def initialize
irb(main):003:2> @feet = 3
irb(main):004:2> end
irb(main):005:1> def report
irb(main):006:2> puts “We have #{@feet} feet”
irb(main):007:2> end
irb(main):008:1> end
=> nil
irb(main):009:0> Body.new.report
We have 3 feet

Classes are also objects themselves and can have instance variables
just as any other object:

irb(main):010:0> class Body
irb(main):011:1> @feet = 2
irb(main):012:1> class << self
irb(main):013:2> attr_accessor :feet
irb(main):014:2> end
irb(main):015:1> end
=> nil
irb(main):016:0> Body.feet
=> 2
irb(main):017:0> class Body
irb(main):018:1> def self.report
irb(main):019:2> puts “We have #{@feet} in the class Body”
irb(main):020:2> end
irb(main):021:1> end
=> nil
irb(main):022:0> Body.report
We have 2 in the class Body

Now, the variable @feet above is a different object from the @feet in
my first example. In fact you can have both and they won’t interfere.
You just have to understand who is “self” in each context:

irb(main):023:0> class Body
irb(main):024:1> @feet = 2
irb(main):025:1> class << self
irb(main):026:2> attr_accessor :feet
irb(main):027:2> def class_report
irb(main):028:3> “We have #{@feet} in class Body”
irb(main):029:3> end
irb(main):030:2> end
irb(main):031:1> def initialize
irb(main):032:2> @feet = 3
irb(main):033:2> end
irb(main):034:1> def report
irb(main):035:2> “We have #{@feet} in the instances of class Body”
irb(main):036:2> end
irb(main):037:1> end
=> nil
irb(main):038:0> Body.feet
=> 2
irb(main):039:0> Body.report
We have 2 in the class Body
=> nil
irb(main):040:0> b = Body.new
=> #<Body:0xb7c2c4fc @feet=3>
irb(main):041:0> b.report
=> “We have 3 in the instances of class Body”

Hope this helps,

Jesus.

On Wednesday 20 August 2008 00:38:43 Ron G. wrote:

b=Body.new
b.report

Why is it in the above class the first puts prints correctly but the second
puts doesn’t have a value for the instance variable?

Well, in this case, you’re defining an instance variable… on Body, the
class:

class Body
@feet = 2

You see, classes are objects, too. You can treat them like normal
objects:

b = Body
c = b.new

The normal way to do what I think you’re wanting to do here is:

class Body
def initialize
@feet = 2
end
end

By the way, you can leave out initialize if you have nothing to
initialize.

Of course, if you’re only supporting humans, you could do this:

class Body
FEET = 2
def report
puts “We have #{FEET} feet”
end
end

One more thing: I don’t often use instance variables directly. That
gives me
more flexibility – I can do something like this:

class Body
attr_reader :feet
def initialize
@feet = 2
end
def report
puts “We have #{feet} feet”
end
end

That way, I could change to using a constant without touching the
“report”
method. The next version would look like this:

class Body
FEET = 2
def feet
FEET
end

end

But it’s getting a bit silly talking about feet, so I’ll stop.