Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What criteria justifies using a Module over a Class in Ruby?

Tags:

ruby

I'm reading my ruby book. Looking at the code below,

module Destroy
  def destroy(anyObject)
    @anyObject = anyObject
    puts "I will destroy the object: #{anyObject}"
  end
end

class User
  include Destroy
  attr_accessor :name, :email
  def initialize(name,email)
    @name  = name
    @email = email
  end
end

my_info = User.new("Bob","[email protected]")
puts "So your name is: #{my_info.name} and you have email #{my_info.email}"

user = User.new("john","[email protected]")
user.destroy("blah")

I could've just created another method inside my class. Why would I want to do this? Why would I want to use a module? It's not like embedding this into other classes is any easier than just using normal inheritance.

like image 712
Muntasir Alam Avatar asked Jul 02 '16 00:07

Muntasir Alam


2 Answers

You can think of a module and the methods and constants inside of it as more of providing utility functions and actions that you can include to other objects as you see fit. For example, if you wanted to use destroy function in the objects Foo and Bar you would do similarly:

class Foo
  include Destroy
  # other code below
end

class Bar
  include Destroy
  # other code below
end

Now any Foo or Bar object has access to all the methods or constants inside of destroy.

Modules define a namespace, a sandbox in which your methods and constants can play without having to worry about being stepped on by other methods and constants. The ruby docs goes into more depth about this and includes a good example practical of when you would want to use it as seen below:

module Debug
  def whoAmI?
    "#{self.type.name} (\##{self.id}): #{self.to_s}"
  end
end
class Phonograph
  include Debug
  # ...
end
class EightTrack
  include Debug
  # ...
end
ph = Phonograph.new("West End Blues")
et = EightTrack.new("Surrealistic Pillow")
ph.whoAmI?  »   "Phonograph (#537766170): West End Blues"
et.whoAmI?  »   "EightTrack (#537765860): Surrealistic Pillow"

In this example, every class that includes Debug has access to the method whoAmI? and other methods and constants that Debug includes without having to redefine it for every class.

like image 73
Dom Avatar answered Oct 21 '22 03:10

Dom


Some programming languages such as C++, Perl, and Python allow one class to inherit from multiple other classes; that is called multiple inheritance. Ruby does not support multiple inheritance. That means each class can only inherit from one other class. However, there are cases where a class would benefit by acquiring methods defined within multiple other classes. That is made possible by using a construct called module.

A module is somewhat similar to a class, except it does not support inheritance, nor instantiating. It is mostly used as a container for storing multiple methods. One way to use a module is to employ an include or extend statement within a class. That way, the class gains access to all methods and objects defined within the module. It is said that the module is mixed in the class. So, a mixin is just a module included in a class. A single module can be mixed in multiple classes, and a single class can mix in multiple modules; thus, any limitations imposed by Ruby's single inheritance model are eliminated by the mixin feature.

Modules can also be used for namespacing. That is explained in this post at the Practicing Ruby website.

like image 31
BrunoF Avatar answered Oct 21 '22 03:10

BrunoF