Hey Robert!
Let me add to that that usually you want to associate a variable with
the class instance or with instances. Class variables (the ones with
@@) have some strange properties that sometimes lead to surprising
behavior. I generally recommend to not use them. Instance
variables in classes are much simpler to handle and much clearer and
cleaner IMHO.
Just to make things more clear,
I'm not sure about "more clear" with your example...
irb(main):001:0> class Test
irb(main):002:1> @@v1 = 0 # class variable?
irb(main):003:1> @v2 = 1 # ???
irb(main):004:1> def initialize
irb(main):005:2> @v3 = 2 # instance variable?
irb(main):006:2> end
irb(main):007:1> def one
irb(main):008:2> @@v1
irb(main):009:2> end
irb(main):010:1> def two
irb(main):011:2> @v2
irb(main):012:2> end
irb(main):013:1> def three
irb(main):014:2> @v3
irb(main):015:2> end
irb(main):016:1> end
=> nil
irb(main):017:0> t = Test.new
=> #<Test:0xb7dc6574 @v3=2>
irb(main):018:0> t.one
=> 0
irb(main):019:0> t.two
=> nil
irb(main):020:0> t.three
=> 2
What is the correct names of v1, v2 and v3? v1 is a class variable,
but what about v2 and v3? We can say that v3 belongs to the class
instance (we saw that after creating the class v3 is on the output
<Test:0xb7dc6574 @v3=2>)on t, but v2 belongs to the class Test?
In fact you have v2, v2 and v3 which shows a bit unfortunate naming because these are three different things. They are all instance variables only that the first v2 is an instance variable of the class object while the second v2 is an instance variable of each Test instance. These are not the same nor do they interfere with each other.
The answer is the difference to create the variables just after the
class statement and before the initialize method OR create it in the
initialize method, right?
Yes. And you can create them even later. Instance variables can spring into existing any time (i.e. during any method execution, see also #instance_variable_get, ..set etc). Ruby is different than other OO languages where you usually have to declare variables. In Ruby, you just use them. Whenever you do @something=x then the instance that is currently referred to by self will have an instance variable named "something".
And v2 is not reached by the two method, but if I change the class and
insert
irb(main):026:0> class Test
irb(main):027:1> def self.four
irb(main):028:2> @v2
irb(main):029:2> end
irb(main):030:1> end
and use
irb(main):032:0> t.class.four
=> 1
I can reach it. So where v1 and v2 exactly are named and belongs to? I
can see that each t haves it's own v3, but still didn't get the way
the or ones are. How v1 and v2 are located on different places.
Kind of
+-------+ +-----+
Test +-----+ t |
+-------+ +-----+
@@v1? | | @v3 |
@v2? | +-----+
+-------+
You're missing @v2 in the right object.
Maybe v1 and v2 are on the same place (the Test instance - v1 needs to
be shared by all Test's, right?) but just can be reached on different
ways (v2 using four)?
Yes.
On the pickaxe we have an example
class SongList
MaxTime = 5*60 # 5 minutes
def SongList.isTooLong(aSong)
return aSong.duration > MaxTime
end
end
On this case, MaxTime resides on the same place that v2 or not?
Because if I change SongList and add
class SongList
def isTooLong(aSong)
return aSong.duration > MaxTime
end
end
and use
s = SongList.new
s.isTooLong(<song here>)
I have a valid result, but something like
irb(main):057:0> class SongList2
irb(main):058:1> @maxtime = 5*60
irb(main):059:1> def SongList2.isTooLong(t)
irb(main):060:2> return t > @maxtime
irb(main):061:2> end
irb(main):062:1> def isTooLong(t)
irb(main):063:2> return t > @maxtime
irb(main):064:2> end
irb(main):065:1> end
=> nil
irb(main):066:0> s2 = SongList2.new
=> #<SongList2:0xb7d733d8>
irb(main):067:0> s2.isTooLong(301)
ArgumentError: comparison of Fixnum with nil failed
from (irb):63:in `>'
from (irb):63:in `isTooLong'
from (irb):67
from (null):0
irb(main):068:0> SongList2.isTooLong(301)
=> true
irb(main):069:0> SongList2.isTooLong(30)
=> false
gives me that error, so there is also a scope difference on a constant
like MaxTime and a variable like @maxtime, defined on the class body?
The trick is in the lookup: @something always refers to the current instance at the moment of execution. Your instance method isTooLong (which btw. in Ruby convention would be named too_long?) refers to a @maxtime instance variable of the SongList2 instance - as these instances don't have a @maxtime you get nil.
Constants are looked up via in class scope - naturally because you cannot have constances in an instance.
Kind regards
robert
···
"Eustáquio Rangel de Oliveira Jr." <eustaquiorangel@yahoo.com> wrote: