my face
About Me

Published Posts

All Posts

New Post


View by Tag:

interviewing, code, testing, philosophy, blog, wantmyjob, virtualization, railsmud, heroku, ruby, published, neoarchaeology, railsgame, rails, juggernaut, astrino, cheaptoad, shannaspizza, mongodb, refactorit, devise


FeedBurner picture


Online Portfolio

Resume

Profile on LinkedIn

Recommend Me

Ruby Classes and Class Methods

Posted: 2 years ago (2007-11-13 23:00:59 UTC ) / Updated: 14 months ago (2009-06-01 22:28:03 UTC )

Imported from WordPress

Originally posted on 2007-11-13 23:00:59

If you already understand Ruby's self variable and have a basic grasp of eigenclasses (aka singleton classes, metaclasses and several other things) then you're ready to really understand how Ruby defines methods in a class.

Sadly, this is more complex than it appears.

The easy stuff, using 'def' to define a simple class, is straightforward. But when you ask about the equivalent of static methods (also called class methods), there's more going on than you think. The classic 'static' method is "new". To make a new string, you'd type "myvar = String.new". In Ruby, this is actually a method call defined on the 'String' object. Not an instance of String -- the method is defined on the class object itself. So "new" is defined pretty much (but not quite) like these methods are:

def String.gooey

"Ew! Gooey!\n"
end

myvar = "blah!"

def myvar.gooey
"Yuck, that's all gooey"
end

print String.gooey # prints out "Ew! Gooey!"
print myvar.gooey # prints out "Yuck, that's all gooey"


Remember how Ruby allows you to define a method that's only valid on one specific instance object? "Class methods" or "static methods" are just methods defined on the type object for that class.

"Type object for that class"? That's a weird phrase. Its meaning is strongly related to the fact that you need to capitalize class names when you define them -- just like you capitalize constants. When you make a class, you're really making a constant that points to your new class's class object.

class MyClass

def foo; "foo!"; end
end

p MyClass # prints out "MyClass"
p MyClass.class # prints out "Class"


So your new "MyClass" is actually a constant, pointing to an instance of Class. It's as though you had said:
OtherClass = Class.new

OtherClass.class_eval do
def foo; "foo!"; end
end

In fact, it's *exactly* like that. A new class declaration just makes a new object of type Class (if it doesn't already exist) and then does a class_eval in it of whatever you told it to run. Remember, defining a class is just more Ruby code that runs in your class's context.

All of this means that if you did the bit above, but instead of "OtherClass = Class.new" you said "otherclass = Class.new", you'd have a type that wasn't a constant. It's nice to be able to refer to your class by a constant, stable name, but Ruby doesn't actually force you to. If you want to make all of your classes be dynamic, or put them in a big hash table, or use them and then completely lose track of them, that's up to you. Ruby won't stop you.

In fact, though, Ruby class methods are slightly weirder than that. Remember the "String.gooey" example up above? That's actually defined in String's singleton class, because that's what the syntax "def object.function" syntax does. It puts it in the singleton class for "object". And all of that means that if you're running in a method of String, you can't directly see these methods. For instance:

def String.fooblah   # A method in String's singleton class

"fooblah!"
end

class String
def my_string_method # A method within String itself
print String.fooblah # this is fine
print fooblah # but this gives an error -- fooblah isn't visible here
end
end


Remember that modules act just like classes through all of this. A Ruby module is basically just a bag of methods that a class can choose to include.

Previous: And then... / Next: Ruby Type Coercion

Edit | Destroy | See All Posts

blog comments powered by Disqus