Class << my_instance and class variables


#1

Hi,

When running this code,

class A
def initialize(i)
@value = i
end
end

a = A.new(3)

class << a
@@v = 5
def test
@value>@@v
end
end

a.test

I get a warning:
“class variable access from toplevel singleton method”

From my understanding, the test method is added to the class specific
to object a, and other instances of A don’t have access to that
method. The class variable @@v is also added to the same object
specific class. But then, what exactly does this warning mean, and how
bad is it?

Thanks

Raph


#2

“R” == Raphael B. removed_email_address@domain.invalid writes:

R> method. The class variable @@v is also added to the same object
R> specific class.

Are you sure ?

moulon% ruby -e ‘class << Object.new; @@a = 12 end; p @@a
-e:1: warning: class variable access from toplevel singleton method
12
moulon%

Guy Decoux


#3

On 5/10/06, ts removed_email_address@domain.invalid wrote:

“R” == Raphael B. removed_email_address@domain.invalid writes:

R> method. The class variable @@v is also added to the same object
R> specific class.

Are you sure ?

moulon% ruby -e ‘class << Object.new; @@a = 12 end; p @@a
-e:1: warning: class variable access from toplevel singleton method
12

I was not sure :wink:

In the mean time I read this very interesting article:
http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html

So methods are added to the object specific class (the metaclass as
identified in why’s article), but class variables are added to the
class of which the object is an instance. Why the difference?

Further on this, if I defined a second instance and try to call test:
b=A.new(6)
b.test

I get the error that test is a private method:
NoMethodError: private method `test’ called for #<A:0xb7cbf5ec @value=6>

so it seems it was added to A, but marked as private.

Are there any good reading about this?
Oh, and about my initial question: how bad is the warning I get?

Raph


#4

thanks Guy for your explanations!

ruby is trying to say that the variable @@v will be defined in Object,
because there is no other class where it can define it.

I didn’t (and still can’t :wink: translate the message “class variable
access from toplevel singleton method” to your explanation of it.

Anyway, I started to play with class instance variables, and got this
code working, if anyone’s interested:

class A
def initialize(i)
@value = i
end

def test_in_class
@value>@@v
end
end

a = A.new(3)

class << a
@cvalue = 5
class << self
attr_reader :cvalue
end
def test
@value>(class << self; self; end).cvalue
end
end

a.test

Cheers

Raph


#5

“R” == Raphael B. removed_email_address@domain.invalid writes:

R> So methods are added to the object specific class (the metaclass as
R> identified in why’s article), but class variables are added to the
R> class of which the object is an instance.

Well, no. class variables (i.e @@) are added in the class which is
cuurently in scope.

R> Further on this, if I defined a second instance and try to call test:
R> b=A.new(6)
R> b.test

When you do this, ruby find the method Kernel#test which is a private
method. This is why it give a warning.

R> so it seems it was added to A, but marked as private.

No, it was added to the singleton class of `a’, you have just chosen a
bad
name for your method (test) :slight_smile:

R> Oh, and about my initial question: how bad is the warning I get?

ruby is trying to say that the variable @@v will be defined in Object,
because there is no other class where it can define it.

Guy Decoux