代码之家  ›  专栏  ›  技术社区  ›  Ryan Ahearn

是否可以从一个类内部调用一个模块函数,这个类也在该模块中

  •  5
  • Ryan Ahearn  · 技术社区  · 14 年前

    在这个Ruby代码中:

    Module M
      Class C < Struct.new(:param)
        def work
          M::helper(param)
        end
      end
    
      def helper(param)
        puts "hello #{param}"
      end
    end
    

    当我尝试运行时,出现“M:Module”的未定义方法“helper”错误

    c = M::C.new("world")
    c.work
    

    M::helper("world") 直接从另一个班级学习很好。类不能调用在同一模块中定义的模块函数吗?除了把类移到模块外,还有别的方法吗?

    4 回复  |  直到 14 年前
        1
  •  4
  •   Gishu    14 年前

    为了调用 M::helper 你需要把它定义为 def self.helper; end 为了进行比较,请查看下面修改的代码段中的helper和helper2

    module M
      class C < Struct.new(:param)
        include M     # include module to get helper2 mixed in
        def work
          M::helper(param)
          helper2(param)
        end
      end
    
      def self.helper(param)
        puts "hello #{param}"
      end
    
      def helper2(param)
        puts "Mixed in hello #{param}"
      end
    end
    
    c = M::C.new("world")
    c.work
    
        2
  •  4
  •   Eimantas    14 年前

    应该在module方法前面加上 self

    module M
      class C < Struct.new(:param)
        def work
          M::helper(param)
        end
      end
    
      def self.helper(param)
        puts "hello #{param}"
      end
    end
    
        3
  •  2
  •   Adrian    14 年前

    C helper M 帮手 不在 M 的单身班。而且,你一直这么说 帮手 帮手 模块功能将使代码正常工作:

    module M
      class C < Struct.new(:param)
        def work
          M::helper(param)
        end
      end
    
      module_function
    
      def helper(param)
        puts "hello #{param}"
      end
    end
    

    module M
      class C < Struct.new(:param)
        include M
    
        def work
          helper(param)
        end
      end
    
      def helper(param)
        puts "hello #{param}"
      end
    end
    

    在第一个例子中, 帮手 被投入 M module_function M 的方法 C 以便 我可以用它们。另一个不同之处是,在第一种情况下,您可以拨打 M.helper 从你代码的任何地方。第二分钟,你就可以打电话了 帮手 C 帮手 私人:

    module M
      class C < Struct.new(:param)
        include M
    
        def work
          helper(param)
        end
      end
    
      private
      def helper(param)
        puts "hello #{param}"
      end
    end
    
        4
  •  1
  •   Kashyap    8 年前

    以下是一些解释:

    ruby docs .

    模块是方法和常量的集合。模块中的方法可以是实例方法或模块方法。实例方法在类中显示为方法当模块包含在内时,模块方法不包含在内。 相反地,可以在不创建封装对象的情况下调用模块方法,而实例方法则不可以(参见模块#模块#功能。)

    self.methodname

    在这种情况下,当您调用 M::helper 你真的在做什么 M.helper 当你从C++开发者的角度来看它的时候。在本例中,接收器是Module对象(ruby内置类型Module的实例)。


    理解这一点的另一种方法是理解接收方的概念,每个方法调用都包含一个接收方和方法名(+可选参数和代码块)。接收器可以是 Module object , Class object 或用户定义类的实例。

    如果要调用模块中定义的实例方法,则必须通过 including

    因此,在这种情况下,另一种解决方案可以是:

    module MM
      def helper(param)
        puts "hello #{param}"
      end
    
      class ReceiverClass
        include MM           # add helper() to ReceiverClass
      end
    
      class C < Struct.new(:param)
        def work
          ReceiverClass.new.helper(param)
        end
      end
    end
    
    c = MM::C.new("world")
    c.work