rubyguides

Ruby keyword: class

class Name

class is the keyword that puts a class into existence. It is reserved by the parser, so you cannot use it as a variable name and you cannot redefine it the way you can with a method. Once the body runs, the whole class ... end expression evaluates to a Class object, which is occasionally useful for assigning the class to a constant or for reflection.

klass = class Box
          def contents = "stuff"
        end

klass           # => Box
klass.new.contents # => "stuff"

That Class return is the reason class is technically an expression, not a statement — even though almost everyone reads it as a declaration.

Syntax

class has three syntactic shapes, and the rule about what each one opens is the part most beginners get wrong.

FormWhat it opens
class NameA new class, inheriting from Object
class Name < SuperA new class with an explicit superclass
class << exprThe singleton class of expr (e.g. class << self inside a class body)
class Animal
  def speak
    "..."
  end
end

class Dog < Animal
  def speak
    "Woof"
  end
end

Dog.new.speak # => "Woof"

Picking the right form up front matters. A misplaced class keyword is one of the most common sources of “why is this method on the wrong object?” bugs.

Default superclass is Object

Without <, the new class inherits from Object. If you want the most minimal root, use < BasicObject instead — Object itself mixes in Kernel, so the behavior of your “blank” class is not actually blank.

class Bare < BasicObject
end

Bare.ancestors # => [Bare, BasicObject]

Object is fine for almost every real class. Reach for BasicObject when you are building something genuinely independent of the standard object protocol (a proxy, a DSL value, an internal IR).

Reopening classes

A second class Name ... end block with the same constant name reopens the existing class. The superclass becomes optional on the reopen, but specifying a different one than the original definition raises TypeError:

class C; end
class C < String; end
# TypeError: superclass mismatch for class C

Reopening is the basis of Ruby’s open-class model and is how gems add methods to core types. Monkey-patching String, Array, and Hash is the same mechanism as adding a method to your own class — the difference is just who owns the file.

class String
  def shout
    upcase + "!"
  end
end

"hi".shout # => "HI!"

Reach for monkey-patches only on classes you own. Reopening String inside your application code is fine in a one-off script; reopening it from a gem that other people will load is a good way to make enemies.

Singleton classes

class << expr opens the singleton class of expr. The singleton class is the hidden class Ruby uses to hold methods that belong to one specific object rather than to a whole type. Inside another class body, the idiomatic form is class << self, which defines class-level methods:

class Counter
  class << self
    def start_at_zero
      @count = 0
    end

    def increment
      @count += 1
    end
  end
end

Counter.start_at_zero  # => 0
Counter.increment      # => 1

class << self is preferred over a chain of def self.foo lines when you are defining several class methods, because you write def once and the methods stay grouped.

You can attach a method to a single object with class << obj instead of def obj.method. The two forms are exactly equivalent — choose whichever reads better in context.

Common gotchas

Three things that bite people:

  • class is a reserved keyword, not a method. def class; end is a SyntaxError, and send(:class, ...) is not a thing.
  • The default superclass is Object, not BasicObject. If you want a class with the absolute minimum of inherited methods, write < BasicObject explicitly.
  • module Outer::Inner; end raises NameError if Outer is not already defined, while nested module Outer; module Inner; end; end works without that requirement. The same rule applies to class A::B; end. The nested form is also the one that puts Outer into Module.nesting for Inner, which changes constant lookup inside the body.

A class is itself an instance of Class, which inherits from Module. That is why klass.is_a?(Module) returns true for any class — a useful fact when you are writing code that has to accept both modules and classes.

See also

  • def keyword — the keyword that puts methods inside a class body.
  • instance_of? — checks whether an object’s class is exactly a given class.
  • is_a? — checks the inheritance chain built by <.