Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When do we use ruby module vs using class composition?

A question similar to this has been asked before, but I am asking specifically about using composition as an alternative to using module mixins.

class Helper
  def do_somthing
  end
end

If I need to 'use' a class but not inherit it , I would simply compose it and use it.

class MyStuff
  def initialize
    helper = Helper.new
    helper.do_something
  end
end

Why would I like to create a module for this:

 module Helper
   def do_something
   end
 end

class MyStuff
  include Helper
end

The only difference I see is there wont be many Helper objects lying around if I use modules. But I don't see anything with more objects lying around vs less bigger objects.

Moreover, I don't know if I need to subclass it in the future. So how do I decide if the users of my library want to use a module mixin, or would want to use composition?

like image 591
codeObserver Avatar asked Apr 02 '13 01:04

codeObserver


3 Answers

When the relationship between Helper and the MyStuff class is one of ownership, use composition. This is known as a "has-a" relationship. For example, let's say you have Person class and a Car class. You would use composition because a person has a car:

class Person
  def initialize
    @car = Car.new
  end
end

class Car
  def accelerate
    # implementation
  end
end

When Helper "acts like" MyStuff, use a module mixin. Helper, in this case, takes on the role of MyStuff. This is a bit different than a "is-a" relationship, which would imply that you should use traditional inheritance. For example, let's say we have a Person class and a Sleeper module. A person takes on the role of a sleeper sometimes, but so do other objects--instances of Dog, Frog, or maybe even Computer. Each of those other classes represent something that can go to sleep.

module Sleeper
  def go_to_sleep
    # implementation
  end
end

class Person
  include Sleeper
end

class Computer
  include Sleeper
end

Sandi Metz's Practical Object-Oriented Design in Ruby is an excellent resource for these topics.

like image 90
Michael Stalker Avatar answered Oct 06 '22 21:10

Michael Stalker


That is a matter of “Duck Typing”. If you want your class to behave like a Helper, you do include. Whether you are to encapsulate Helper behaviour, the right choice is require.

Mixing Enumerable in, you give your class the huge load of methods by implementing the only each method. Wrapping Array you may hide iteration from others and use it for holding your data only. And vice versa.

like image 2
Aleksei Matiushkin Avatar answered Oct 06 '22 23:10

Aleksei Matiushkin


Modules mixin is more like multiple inheritance, so follow the usual inheritance vs composition rule — is-a or has-a. By the way, it's include Helper, not require 'Helper'.

like image 1
shock_one Avatar answered Oct 06 '22 23:10

shock_one