Newbie question: About class variable and class_eval

M

mzhang.cn

Hi all,
Please look at the following code
-----------------------------------------------------------
class Cls
@@cv = 0
def initialize
@iv = 1
end
end

c=Cls.new
Cls.class_eval { def iv() @iv end }
puts c.iv
Cls.class_eval { def cv() @@cv end }
puts c.cv
-------------------------------------------------------------
When running this code snippet, I got the result:
$ ruby classvar.rb
1
classvar.rb:11:in `cv': uninitialized class variable @@cv in Object
(NameError).

Why I can't get the class variable in class_eval?
 
S

Sean O'Halpin

Hi all,
Please look at the following code
-----------------------------------------------------------
class Cls
@@cv =3D 0
def initialize
@iv =3D 1
end
end

c=3DCls.new
Cls.class_eval { def iv() @iv end }
puts c.iv
Cls.class_eval { def cv() @@cv end }
puts c.cv
-------------------------------------------------------------
When running this code snippet, I got the result:
$ ruby classvar.rb
1
classvar.rb:11:in `cv': uninitialized class variable @@cv in Object
(NameError).

Why I can't get the class variable in class_eval?

Class variables (i.e. starting with @@) have wierd scoping.
The @@cv you refer to in your closure is looking for resolution
in the scope of the class in which the closure is defined, in this case
the top level Object class.

The only way I know of to get the effect you want is to use string eval:

Cls.class_eval "def cv() @@cv end "

Regards,

Sean
 
L

Lionel Thiry

(e-mail address removed) a écrit :
Hi all,
Please look at the following code
-----------------------------------------------------------
class Cls
@@cv = 0
def initialize
@iv = 1
end
end

c=Cls.new
Cls.class_eval { def iv() @iv end }
puts c.iv
Cls.class_eval { def cv() @@cv end }
puts c.cv
-------------------------------------------------------------
When running this code snippet, I got the result:
$ ruby classvar.rb
1
classvar.rb:11:in `cv': uninitialized class variable @@cv in Object
(NameError).

Why I can't get the class variable in class_eval?

You may just avoid class variable @@cv and use class instance variable
instead:

---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<
class Cls
@cv = 0
def initialize
@iv = 1
end
end

c=Cls.new
Cls.class_eval { def iv() @iv end }
puts c.iv
Cls.class_eval { class <<self; def cv() @cv end; end }
puts Cls.cv
Cls.class_eval { def cv() self.class.cv end }
puts c.cv
---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<

It works because classes in ruby are objects themselves.
 
D

David A. Black

Hi --

---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<
class Cls
@cv = 0
def initialize
@iv = 1
end
end

c=Cls.new
Cls.class_eval { def iv() @iv end }
puts c.iv
Cls.class_eval { class <<self; def cv() @cv end; end }

You can get at that more directly:

def Cls.cv; @cv; end

(unless you need something from the surrounding scope, of course).


David
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,585
Members
45,080
Latest member
mikkipirss

Latest Threads

Top