Let's say I have a bunch of related functions that have no persistent state, say various operations in a string differencing package. I can either define them in a class or module (using self
) and they can be accessed the exact same way:
class Diff
def self.diff ...
def self.patch ...
end
or
module Diff
def self.diff ...
def self.patch ...
end
I can then do Diff.patch(...)
. Which is 'better' (or 'correct')?
The main reason I need to group them up is namespace issues, common function names are all used elsewhere.
Edit: Changed example from matrix to diff. Matrix is a terrible example as it does have state and everyone started explaining why it's better to write them as methods rather than answer the actual question. :(
In your two examples, you are not actually defining methods in a Class
or a Module
; you are defining singleton methods on an object which happens to be a Class
or a Module
, but could be just about any object. Here's an example with a String
:
Diff = "Use me to access really cool methods"
def Diff.patch
# ...
end
You can do any of these and that will work, but the best way to group related methods is in a Module
as normal instance methods (i.e. without self.
):
module Diff
extend self # This makes the instance methods available to the Diff module itself
def diff ... # no self.
def patch ...
end
Now you can:
- use this functionality from within any Class (with
include Diff
) or from any object (with extend Diff
)
- an example of this use is the
extend self
line which makes it possible to call Diff.patch
.
- even use these methods in the global namespace
For example, in irb
:
class Foo
include Diff
end
Foo.new.patch # => calls the patch method
Diff.patch # => also calls Diff.patch
include Diff # => now you can call methods directly:
patch # => also calls the patch method
Note: the extend self
will "modify" the Diff
module object itself but it won't have any effect on inclusions of the module. Same thing happens for a def self.foo
, the foo
won't be available to any class including it. In short, only instance methods of Diff
are imported with an include
(or an extend
), not the singleton methods. Only subclassing a class will provide inheritance of both instance and singleton methods.
When you actually want the inclusion of a module to provide both instance methods and singleton methods, it's not completely easy. You have to use the self.included
hook:
module Foo
def some_instance_method; end
module ClassMethods
def some_singleton_method; end
end
def self.included(base)
base.send :extend, ClassMethods
end
def self.will_not_be_included_in_any_way; end
end
class Bar
include Foo
end
# Bar has now instance methods:
Bar.new.some_instance_method # => nil
# and singleton methods:
Bar.some_singleton_method # => nil
The main difference between modules and classes is that you can not instantiate a module; you can't do obj = MyModule.new
. The assumption of your question is that you don't want to instantiate anything, so I recommend just using a module.
Still you should reconsider your approach: rather than using arrays of arrays or whatever you are doing to represent a Matrix, it would be more elegant to make your own class to represent a matrix, or find a good class that someone else has already written.
Ruby Modules are used to specify behaviour, pieces of related functionality.
Ruby Classes are used to specify both state and behaviour, a singular entity.
There is a maxim in software design that says that code is a liability, so use the less code possible. In the case of Ruby, the difference in code lines is cero. So you can use either way (if you don't need to save state)
If you want to be a purist, then use a Module, since you won't be using the State functionality. But I wouldn't say that using a class is wrong.
As a trivia info: In Ruby a Class is a kind of Module.
http://www.ruby-doc.org/core-1.9.3/Class.html
The following also works
Matrix = Object.new
def Matrix.add ...
def Matrix.equals ...
That's because so-called "class methods" are just methods added to a single object, and it doesn't really matter what that object class is.
As a matter of form, the Module is more correct. You can still create instances of the class, even if it has only class methods. You can think of a module here as a static class of C# or Java. Classes also always have the instance related methods (new
, allocate
, etc.). Use the Module. Class methods usually have something to do with objects (creating them, manipulating them).