Skip to content

06 — Classes and modules

One line: A Ruby class is an object whose method table is never closed, its @variables can be reached only through methods, and a module is a namespace, a mixin, or both — and each of those rules is one a Python programmer half-knows and needs to see measured.

This chapter is the object-oriented core: where state lives and who can see it (@x, private, protected, @@count), how a class is assembled (class String reopened, include, extend, prepend) and how a call finds its method (ancestors, super, method_missing), then the two things that give names their meaning — constants with their lexical lookup, and modules as namespaces. Every page builds a small class, asks it a numbered list of questions, and prints the answers; the Python twin asks the same questions of a Python class and prints its answers in the same rows.

For a Python programmer most of the vocabulary carries over and most of the rules do not. Attributes are public in Python and unreachable without a method in Ruby; private in Ruby restricts the receiver, not the calling class; a class attribute assigned through a subclass creates a shadow in Python and changes the parent's value in Ruby; a second class Foo statement reopens the class in Ruby and replaces it in Python. Where the two agree — inheritance through a chain, an explicit super in a constructor, a mutable class-level list that everybody shares — the twin's output makes that visible too. The model-level questions (singleton classes, new versus initialize, eql?/hash, refinements) are the next chapter, 07 — The object model.

Lesson Level The one thing
Instance variables are private 101 acct.owner is a method call, so @owner is unreachable until attr_reader writes that method; an unset @x reads as nil
private means "no receiver" 201 a private method may be called only receiverless or as self.x; protected admits another instance; send bypasses, public_send does not
Classes are open 201 a second class String adds to the one String; a redefinition warns under -w; only the superclass may not change
Mixins: include, extend, prepend 201 include goes behind the class in ancestors, prepend in front so its method runs first, extend into one object
Method lookup walks ancestors; super continues it 301 a call walks the chain left to right; bare super passes the parameters' current values, super() passes nothing; the walk ends in method_missing
Constants are found lexically, then through ancestors 301 Module.nesting first, then ancestors, then Object; class Foo::Bar cannot see Foo's constants; reassignment warns by default
Class variables are shared with subclasses 201 @@count is one slot for the whole hierarchy and a subclass assignment changes the parent's; a class-level @count is per class
A module is a namespace, and cannot be instantiated 101 Shop::Cart, Shop::VERSION, Shop.version; :: reaches a constant and . calls a method; Shop.new does not exist

Read more