tags:

views:

68

answers:

4

Is it possible to declare static methods in a module in ruby?

module Software
  def self.exit
    puts "exited"
  end
end

class Windows
  include Software

  def self.start
    puts "started"
    self.exit
  end
end

Windows.start

The example above will not print out "exited".

Is it only possible to have instance methods in a module?

Thanks

+1  A: 

It is possible to include static methods in a module:

module Software

  def self.exit
    puts "exited"

  end
end

Software.exit

Running this prints 'exited' as expected.

Chris Bunch
but do i have to include this module inside the class for using the static method? cause include does just include instance methods from a module not static?
never_had_a_name
Ah, not sure on that one. An easy fix would be just to call 'Software.exit' inside the Windows class and get rid of the 'include Software' part (not the most elegant fix, but outside of the scope of this question as currently posed).
Chris Bunch
+1  A: 

Define your module like this (i.e. make exit an instance method in the module):

module Software
  def exit
    puts "exited"
  end
end

and then use extend rather than include

class Windows
  extend Software
  # your self.start method as in the question
end

In use:

irb(main):016:0> Windows.start
started
exited
=> nil

Explanation

obj.extend(module, ...) adds to obj the instance methods from each module given as a parameter

...so when used within the context of a class definition (with the class itself as the receiver) the methods become class methods.

mikej
+1  A: 

Two things need to change to be able to call Windows.exit:

  1. Software#exit needs to be an instance method
  2. Windows needs to extend Software, not include it.

This is because extending another module puts that module's instance methods as the current module's class methods, whereas includeing a module puts the methods as new instance methods.

module Software
    def exit
        puts "exited"
    end
end

class Windows
    extend Software

    def self.start
        puts "started"
        self.exit
    end

end

Windows.start

Output is:

started
exited
Mark Rushakoff
+1  A: 

Put your class methods in a nested module, and then override the "included" hook. This hook is called anytime your module is included. Inside the hook, add the class methods to whomever did the include:

module Foo

  def self.included(o)
    o.extend(ClassMethods)
  end

  module ClassMethods

    def foo
      'foo'
    end

  end

end

Now any class including Foo gets a class method named foo:

class MyClass
  include Foo
end

p MyClass.foo    # "foo"

Any non-class methods may be defined in Foo as usual.

Wayne Conrad
(beside: it's MyClass.foo )This approach has the advantage, that you can add non-static functions, too.
Baju
@Baju, either `::` or `.` works there, but I suppose `.` is preferred. I've edited the example. Thanks for pointing that out.
Wayne Conrad
-1. Yuck, this is completely unnecessary. Just use `extend` instead of `include`.
Jörg W Mittag
@Jörg W Mittag, I'm not sure I agree. This allows instance methods and class methods at the same time.
Wayne Conrad