Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the practical differences between a module method and a class method in Ruby?

Tags:

module

class

ruby

What are the differences between

module Logging
  def self.log
    if @logger.nil?
      @logger = Logger.new STDOUT
    end
    @logger
  end
end

and this?

class Logging
  def self.log
    if @logger.nil?
      @logger = Logger.new STDOUT
    end
    @logger
  end
end

They both appear to do the same thing. Why would I choose one over the other?

like image 234
Spencer Wood Avatar asked Dec 11 '22 15:12

Spencer Wood


2 Answers

tl;dr: There are no class methods and module methods in Ruby, only instance methods. Considering that they are both just instance methods, and thus the same thing, there cannot possibly be any difference.


There is no such thing as a "class method" or a "module method" in Ruby. Ruby has exactly one kind of method: instance methods.

We sometimes use the word "class method" or "module method" out of convenience when talking about a certain pattern of using instance methods, but there is no such concept in Ruby. "Class methods" and "module methods" are really just singleton methods of an object which just happens to be an instance of the Module class or the Class class. There is absolutely no difference whatsoever between a singleton method of an object which happens to be an instance of Class, Module, String, Array, Hash, Object, Foo, Bar, Whatever, or Garbledigookidoo.

Oh. Did I mention? Singleton methods don't exist, either. Again, it is a word we use for certain kinds of usages of methods, but they are really just regular boring old instance methods of the singleton class of an object.

However, "instance method of the singleton class of foo" and "instance method of the singleton class of Foo, where Foo is an instance of Class" are really long, and so we shorten them to "singleton method of foo" and "class method of Foo" out of convenience, knowing full well that those are fictions that don't actually exist in the language.

Unlike Java, which has three different kinds of methods (instance methods, static methods, and constructors (which are kinda-sorta like methods)), Ruby has exactly one kind of method: instance methods. No class methods, no module methods, no global methods, no top-level methods, no static methods, no constructors. It does, however, have three kinds of classes: regular classes, singleton classes, and include classes (the latter being classes that get synthesized and injected into the inheritance hierarchy when you call include or prepend). These classes differ mainly in whether methods like Object#class, Class#superclass, and Class#ancestors display them or suppress them. Singleton classes are suppressed by all of them, include classes by the first two, but shown by ancestors.

like image 53
Jörg W Mittag Avatar answered Jan 20 '23 11:01

Jörg W Mittag


Jörg Mittag is correct that there technically are no class methods or module methods. However, I will assume by "class method" you meant "an instance method defined on the singleton class of a Class instance" and by "module method" you meant "an instance method defined on the singleton class of a Module instance".

There is no functional difference between the two. Both define a method within a namespace.

In practice, you'll see that they tend to be used for different purposes. For example, class methods are often to specify different ways to construct an object, e.g. Puzzle.from_textfile. Module methods are just global functions that are put into a single namespace because they are logically related, e.g. Math.sin and Math.abs.

It's also important to note that Ruby also has the concept of a "module function", which is unrelated to this question. The term "module function" refers an class method on a module which has an identical private instance method. These can be created programmatically using Module.module_function, and are useful when a module is intended to be used as both a namespace and a mixin (e.g. Math).

like image 41
Ceasar Bautista Avatar answered Jan 20 '23 10:01

Ceasar Bautista