14 Mar, 2010, Runter wrote in the 1st comment:
Votes: 0
I can't seem to find a method to show all the class variables accessible to an object.

I thought maybe a class variable was simply an instance variable on the class object itself.

class Meh
@@test = "meh"
end

m = Meh.new

p m.instance_variables
p Meh.instance_variables


Quote
[]
[]


If anyone–*cough tyche*– could shed some light on this I would appreciate it.


I would have expected class_variables to be a method for Object.
14 Mar, 2010, Runter wrote in the 2nd comment:
Votes: 0
Okay. To answer my own question class_variables method exists for classes. Not for all objects.

So this was the result.
class Meh
@@test = "meh"
end

p Meh.class_variables

Quote
[:@@test]



I got a little confused by them while doing some meta-programming. I got even more confused by the way class variables from children are shared with parents. Indeed, if you put a class variable in Object everything shares it.
14 Mar, 2010, Chris Bailey wrote in the 3rd comment:
Votes: 0
Shouldn't that be the way it works, since all things are objects?
14 Mar, 2010, Runter wrote in the 4th comment:
Votes: 0
Chris Bailey said:
Shouldn't that be the way it works, since all things are objects?




Here's something dubious I'm not sure what to think of:
class Roar
@@common_var = "lion"
def common_var
@@common_var
end
end

class Mew
@@common_var = "kitty"
def common_var
@@common_var
end
end

cat = Mew.new
bigcat = Roar.new

p cat.common_var
p bigcat.common_var

##somewhere else in the program in the Object namespace.
@@@@common_var = "gorilla"


p cat.common_var
p bigcat.common_var

output
Quote
"kitty"
"lion"
"gorilla"
"gorilla"
14 Mar, 2010, Runter wrote in the 5th comment:
Votes: 0
I suppose what was a little confusing is the way it instantiates classes as a so called first-class-object. The way it's instantiated is by the keyword class.
class Roar   # instantiates a new Class object 
def speak
"mew"
end
end


It's then assigned to a global constant obj called Roar.

In other words, this is the same thing as…
Roar = Class.new


This was confusing for me. It was confusing because this doesn't result in giving Roar the mew method:

Roar = Class.new
def Roar.speak
"mew"
end


Because essentially you're not defining anything for the object itself in the class definition. It's more like a blue-print for a factory object that will define methods on anything created from the factory.

But this code does:

Roar = Class.new
Roar.send(:define_method,:speak) do
"mew"
end


Can't call define_method directly because it's private, but yeah.
14 Mar, 2010, Chris Bailey wrote in the 6th comment:
Votes: 0
Interesting little tidbit there. I'll have to keep that in mind. I really hadn't even thought about it =)
14 Mar, 2010, Runter wrote in the 7th comment:
Votes: 0
Chris Bailey said:
Interesting little tidbit there. I'll have to keep that in mind. I really hadn't even thought about it =)


It's honestly probably not something many people think about. It's pretty much a difference without distinction. Getting more heavy into meta programming is what has brought it to my attention.
14 Mar, 2010, David Haley wrote in the 8th comment:
Votes: 0
You can do interesting things with class metaprogramming. Assuming that Ruby lets you do what Python does here (I'm guessing that it does) you can implement "type-checked class hierarchies". I wrote some code at work to do this: you can mark some methods as overriding superclass methods, you can mark methods as abstract meaning that an object can't be instantiated unless the methods are implemented, and you can add pre-/post-condition checker functions to methods. All of this works by having your classes derive from a special object type which has a metaclass that does some stuff to classes created under it.

EDIT: and I managed to omit what I wanted to say: I've seen similar interesting things happen in Python too, where you have a distinction between creating the class as an object vs. creating the class in code normally, with weird things happening as you add methods depending on where you add them.
14 Mar, 2010, Runter wrote in the 9th comment:
Votes: 0
Yes, while I'm on the subject of what I've found to be confusing…The terminology surrounding this type of code is anything but consistent. I've read in many different places using different terms to describe the metaclass. Seems the term singleton-class is also widely used.

Also seen "ghost class" and "Eigenclass."

It seems the most accepted convention among the ruby community has been singleton-class.

edit: Actually this just shows how confusing the entire thing is. Because the way you were using metaclass was the correct way and I misread it for a moment. The term in the ruby community is erroneously used often, though.

In fact:
Lawl
14 Mar, 2010, David Haley wrote in the 10th comment:
Votes: 0
Heh, yeah, it's pretty strange that there are so many ways of referring to it, to the point that the documentation has no standard term either. Incidentally, reading up on singleton classes in Ruby (e.g. here) it sounds like they mean something yet different: namely the anonymous classes that are created when new methods are added to an object.

Metaclasses in Python at least let you intercept the class creation process. In the example I gave above, when you create a class that inherits from CheckedObject (the class with the metaclass), the metaclass steps in and instruments your class. In fact, even normal objects have metaclasses under the hood that do things. For example, they add the logic to turn class method definitions into actual bound methods. (You can in principle rewrite your own implementation of this logic using your own metaclass if you choose to do so.)

It is pretty confusing though when people don't agree on terminology, or worse use the same words to mean rather different things. It looks like the ghost/eigen/singleton class is actually a fully different concept than the Python metaclass I've been describing.
14 Mar, 2010, Runter wrote in the 11th comment:
Votes: 0
Yes, but that's where it's a little strange. Because the singleton-class of a Class object…i.e. the anonymous class associated with an instance of the Class class…could possibly be referred to as a metaclass. This is where the confusion originated from surrounding the concept in Ruby. However, that still does not make the terms interchangeable.
14 Mar, 2010, David Haley wrote in the 12th comment:
Votes: 0
Oh ok. Yes I agree that a singleton class of a class object – an instance of the Class class – could be a metaclass. Starts to get confusing pretty quickly :tongue:

How much class could a class-chuck chuck if a class-chuck could chuck class?
14 Mar, 2010, Runter wrote in the 13th comment:
Votes: 0
I propose we add to the problem by calling singleton-classes anonymous pointer class references.
14 Mar, 2010, Tyche wrote in the 14th comment:
Votes: 0
class Foo
@@@@a = "class variable"
@a = "class instance variable"
def initialize
@a = "object instance variable"
end
end

class<<Foo
@a = "class metaclass variable"
end
f = Foo.new
class<<f
@a = "object metaclass variable"
end

puts "#{Foo.class_variables} = #{Foo.class_eval '@@a'}"
puts "#{Foo.instance_variables} = #{Foo.instance_variable_get :@a}"
puts "#{(class<<Foo;self;end).instance_variables} = #{(class<<Foo;self;end).instance_variable_get :@a}"
puts "#{f.instance_variables} = #{f.instance_variable_get :@a}"
puts "#{(class<<f;self;end).instance_variables} = #{(class<<f;self;end).instance_variable_get :@a}"



$ ruby vars.rb
@@@@a = class variable
@a = class instance variable
@a = class metaclass variable
@a = object instance variable
@a = object metaclass variable


Diagram of objects


f (object instance)
| @a
|
`f (object metaclass)—-Foo (class instance) —- Object (class instance)
@a | @a
|
`Foo (class metaclass)
@a


Where is class variable @@a stored?
Exercise left for reader.
14 Mar, 2010, Tyche wrote in the 15th comment:
Votes: 0
BTW the "class instance variable @a" above is about what you'd be thinking of, if you were looking for the equivalent of a C++ class's static variables.
14 Mar, 2010, Runter wrote in the 16th comment:
Votes: 0
I don't know, but I'd like to know the answer.

I'm going to assume it's stored in the instance Class since Foo is an instance of Class.
15 Mar, 2010, Tyche wrote in the 17th comment:
Votes: 0
Runter said:
I don't know, but I'd like to know the answer.

I'm going to assume it's stored in the instance Class since Foo is an instance of Class.


They are stored in same exact place instance variables are except only on classes , so in the above case it's defined on Foo class instance.
The instance_variables method doesn't report them, and the class_variables method doesn't report the instance variables.

The problem with class variables is that they are shared among the classes below the highest classes in the iheritance chain on down.
So setting any one in the inheritance chain sets them all…. or something like that. :-(
15 Mar, 2010, David Haley wrote in the 18th comment:
Votes: 0
Isn't that exactly the behavior you'd want with class variables? Isn't the point that they're shared among instances of a class, which by natural inheritance means instances of subclasses as well?
15 Mar, 2010, flumpy wrote in the 19th comment:
Votes: 0
Yes, I think it makes sense, it's just terminology that's hazing things here more than anything I think
15 Mar, 2010, Runter wrote in the 20th comment:
Votes: 0
David Haley said:
Isn't that exactly the behavior you'd want with class variables? Isn't the point that they're shared among instances of a class, which by natural inheritance means instances of subclasses as well?


I guess, but they're unlike C++ class variables. To get that functionality, as tyche already pointed out, you want instance variables on the class instance. Not class variables.

This is something I find undesirable in Ruby. I don't like how unclear the difference between the two is. Especially when the use of sigils makes you assume you know at a glance where this functionality would lie inside of the class construct itself.

class Val
@var = "easily confused" # Initialize our variable?
def initialize
@var = "With this."
end
end


And as I say, I think it is even more easily confused when you make an assumption that class variables are always sigil'd with @@. I suppose it makes sense, because it's the instance variable for the class. So one @ makes sense. But the place that you're able to access it isn't immediately clear. From the materials I've read there's hardly even a mention of the class instance variable. It's usually simply labeled as the wrong place to initialize your instance variables. (Which it may not be if your trying to initialize your instance variables on your class object.)
0.0/48