1

I am trying to access a module function that I have overriden in the class.

module Base
    def Hello
        puts "Hello"
    end
end

class Top

  include Base

  def Hello
    puts "hello from top"
  end

  def Hi
    if p == 1
        Hello
    else
        Base::Hello
    end
  end
end

But I get the following error -

Error:  undefined method `Hello' for Base:Module

Is there any way I can access the module function without using self.Hello in function definition.

2
  • you can't access module function without self Commented May 4, 2016 at 6:45
  • @Veeru Yes, you can. If the method is defined in the module to be an instance method (i.e. without self. preceding it) then inside the class that includes the module it can be accessed as if it were an instance variable, that is, without self. I think what the OP means is that he does not want to define the method with self. But then I want to ask the OP, why is it that you don't want to define the method with self.? If you override the method in the class, you'll have to refer to it in some special way. Commented May 4, 2016 at 7:09

4 Answers 4

3

You demonstrated the complete misunderstanding of OOP concepts. And, BTW, the method names in Ruby are not to be started with capital letter.

One can not just call an arbitrary method somewhere in the class hierarchy. Whether this was possible, the whole OOP would make absolutely no sense.

One might call the super method from within this method:

module Base
  def hello
    puts "Hello"
  end 
end

class Top 
  include Base

  def initialize p
    @p = p 
  end 
  def hello
    if @p == 1
      puts "hello from top"
    else
      super
    end 
  end 
  def hi
    hello
  end 
end

Top.new(1).hi
#⇒ hello from top
Top.new(2).hi
#⇒ Hello

or, one might declare the module function, a.k.a. static function and call it from everywhere:

module Base
  def self.hello
    puts "Hello"
  end
end

class Top
  # NOT NEEDED include Base
  def hello
    puts "hello from top"
  end

  def hi
    if p == 1
      hello
    else
      Base.hello
    end
  end
end
Sign up to request clarification or add additional context in comments.

Comments

1

One way you can do this is to make the module's method a module method rather than an instance method. If you precede the method definition with module_function, then both a module and an instance method will be created. This will enable you to access the module method using the module's name (in this case, BaseModule.hello). I've trimmed your question code to the essentials and illustrated how that would work:

#!/usr/bin/env ruby

module BaseModule

    module_function

    def hello
        puts 'Hello from BaseModule'
    end
end


class MyClass
  include BaseModule

  def hello
    puts 'Hello from MyClass'
  end

  def module_hello
    BaseModule.hello
  end
end

MyClass.new.hello         # Hello from MyClass
MyClass.new.module_hello  # Hello from BaseModule

5 Comments

It's redundant in this case, as is use of module_function itself, since in the example, the sole method is used only as a module method (it could have been defined simply as self.hello). As for copying answers, there were no answers posted when I started working on my answer. In addition, you did not include the module_function approach creating both instance and module methods. BTW, your tone to both the OP and me is rather harsh.
“you did not include the module_function approach creating both instance and module methods”—module_function is just a syntactic sugar for self.. My code does not create instance function, it behaves exactly as yours. If you think, the tone is harsh, feel free to flag anything for moderator attention.
@mudasobwa This is not correct. I just posted a SO question and answer explaining this, at stackoverflow.com/questions/37021084/….
I did not understand, what you have tried to explain. I never said self.foo creates an instance method, furthermore I said exactly an opposite (you might re-read my previous comment.) Since you never used BaseModule#hello as instance function in your example, I made an assumption the goal was to create the module function. That simple.
You said "My code does not create instance function, it behaves exactly as yours." My code does create an instance function, it creates both. Anyway, I think we understand each other now. Thank you for your time and effort on SO, I see by your rep that you have done a lot here.
0

You didn't understand meaning of include! When you include a module to a class methods from a module add to a object inheritance chain. In this way You can call that methods like own.

module A
 def hello
   p 'Hello from A'
 end
end
class MyClass
 include A
end

2.2.2 :010 > mm = MyClass.new
=> #<MyClass:0x00000000ecaa68> 
2.2.2 :011 > mm.hello
"Hello from A"

You can use next in your case:

module B
 def self.hello
   p 'Hello from B'
 end
end
class MyClass
 def my_hello
  B.hello #direct call from module B
 end
end

And one more note: Don't use capitalized name for a method

Comments

0

If you are overwriting a instance method of a module within your class, you can call this method using super.

module Base
  def Hello
    puts "Hello"
  end
end 

class Top
    include Base

   def Hello
     if p == 1
       puts "hello from top"
     else
       super
     end
   end
 end

 t = Top.new
 t.Hello # => "Hello"

2 Comments

Please also describe in words what the code is supposed to do, so the answer is simpler to understand
Although this code may answer the question, providing additional context regarding why and/or how it answers the question would significantly improve its long-term value. Please edit your answer to add some explanation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.