6

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","Bob@example.com")
puts "So your name is: #{my_info.name} and you have email #{my_info.email}"

user = User.new("john","john@example.com")
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.

sawa
  • 165,429
  • 45
  • 277
  • 381
Muntasir Alam
  • 1,777
  • 2
  • 17
  • 26
  • Inheritance isn't the only way to share functionality, and is often neither practical nor possible. – Dave Newton Jul 02 '16 at 01:25
  • Possible duplicate of [Difference between a class and a module](http://stackoverflow.com/questions/151505/difference-between-a-class-and-a-module) – SoAwesomeMan Jul 02 '16 at 04:32

3 Answers3

3

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.

Dom
  • 1,687
  • 6
  • 27
  • 37
  • "#{self.type.name} (\##{self.id}): #{self.to_s}", what does that line mean? My book mentions self very briefly, self points to the module Debug here right? – Muntasir Alam Jul 02 '16 at 01:16
  • Particularly the ## signs as well, never seen that in my life, im just familar with #{variable } – Muntasir Alam Jul 02 '16 at 01:21
  • @cresjoy It's string containing the type name, the id, and a string representation of the object. The extra # is just for formatting as seen in the last two lines of the example which is why it is escaped. The self uses the object that was called to return the information. – Dom Jul 02 '16 at 01:24
2

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.

BrunoF
  • 3,239
  • 26
  • 39
  • Good points, but you should say something about modules that are not intended to be mixins, but merely to house helper (module) methods (defined `def self.mod_method...`) that might be used by various classes. – Cary Swoveland Jul 02 '16 at 01:10
  • Hmm.. Totally didnt know that. So your saying that if Class B inherits from class A, class C can't inherit from class A? – Muntasir Alam Jul 02 '16 at 01:19
  • @cresjoy No. Both classes B and C can inherit from A. However, B can't inherit from both A and C. Each class can only inherit from one other class. However, one class can be inherited by multiple other classes. – BrunoF Jul 02 '16 at 01:39
  • Oh I see. That kind of implementation of B and C inheriting from A seems rather convoluted. Not sure why one would want to do that anyway. Then again I am a newbie programmer. – Muntasir Alam Jul 02 '16 at 01:58
  • Multiple inheritance and namespacing are both irrelevant here. – sawa Jul 02 '16 at 10:44
  • @Cary Swoveland We can store helper class methods (as in your example) by using _extend_ instead of _include_. However, that is still a feature of Ruby's mixin facility. include is used for acquiring instance methods from a module and extend is used to acquire class methods. – BrunoF Jul 02 '16 at 13:03
  • @cresjoy It depends. For instance, we may have a Mammal class with common characteristics for all mammals (e.g., endothermic, vertebrate) and many other classes such as Dog, Cat and so on, which inherit from Mammal. Or a Shape class with common characteristics for many geometric shapes (e.g., line width and color), and many other classes such as Triangle and Square which inherit from Shape. – BrunoF Jul 02 '16 at 13:06
  • @sawa I disagree. The OP is asking about reasons to use a module. Namespacing and "emulating" multiple inheritance are amongst the main reason to use modules in Ruby. – BrunoF Jul 02 '16 at 13:08
  • I was speaking of how, for example, the [Math](http://ruby-doc.org/core-2.2.0/Math.html) module is used. That module contains nothing other than module methods (and constants). – Cary Swoveland Jul 02 '16 at 15:20
0

You are writing a module in the same file as the class, but not necessarily inside the class, but anyway.

For me there are 3 reasons to use a module(more details here):

  1. Modules provide a namespace and prevent name clashes.
  2. Modules implement the mixin facility.
  3. When you have a very complex and dense class, you can split it into modules and include them into the main class.

Your example is fairly simple, it would indeed make more sense to write the method in the class itself, but try to imagine a complex scenario.

fabriciofreitag
  • 2,843
  • 22
  • 26
  • 1
    Your 1 is irrelevant here. 2 is also irrelevant if the purpose is to include the facility in multiple classes, and if not, it does not explain anything. 3 is the relevant case in question, but it is not explaining why you want to do that. – sawa Jul 02 '16 at 10:41
  • Regardless of this scenario, I think is important for the OP to know why and when he would use a module. – fabriciofreitag Jul 02 '16 at 12:30