Ruby module_function,调用模块的私有方法,在模块上的类方法样式中调用显示错误

时间:2023-01-15 20:20:25

test_module.rb

  module MyModule
    def module_func_a
      puts "module_func_a invoked"
      private_b
    end

    module_function :module_func_a

    private
    def private_b
      puts "private_b invoked"
    end
  end

  class MyClass
    include MyModule
    def test_module
      module_func_a
    end
  end

Invoking module function from class

从类调用模块函数

  c = MyClass.new
  c.test_module

Output 1:

$ ruby test_module.rb 
 module_func_a invoked
 private_b invoked

Invoking module function on module in class method style

在类方法样式中调用模块上的模块函数

ma = MyModule.module_func_a

Output 2:

 module_func_a invoked
 test_module.rb:5:in `module_func_a': undefined local variable or method `private_b' for MyModule:Module (NameError)
 from test_module.rb:31

As can be seen from the Output 1 and Output 2 when including the module in a class, no issue occurs when a module's private method gets invoked from a module function while in case when directly invoking the module function on the module in class method style the module's private method, invoked from module function, is not found.

从模块中包含模块的输出1和输出2可以看出,当模块的私有方法从模块函数调用时,如果在类方法样式中直接调用模块上的模块函数,则不会出现问题找不到模块函数调用的模块私有方法。

Can anybody make me understand the reason behind above behavior and whether invoking module function (which in turn invokes module's private method) on module in class method style is possible or not? If possible, then what rectifications are required in my code to do the same?

任何人都可以让我理解上面的行为背后的原因,是否可以在类方法风格的模块上调用模块函数(进而调用模块的私有方法)?如果可能的话,我的代码中需要做哪些修正才能做同样的事情?

2 个解决方案

#1


6  

It works when you include the module in a class, because then all of the module's methods get included in that class (the self in module_func_a points to MyClass, which has also the private_b method).

当你在一个类中包含模块时,它可以工作,因为然后所有模块的方法都包含在该类中(module_func_a中的self指向MyClass,它也有private_b方法)。

In the other situation self points to MyModule, which does not have private_b method. If you wanted it to work both ways, you'd have to either declare private_b as a module method as well, or simply add the line extend self to MyModule, so that all it's methods would become module methods.

在另一种情况下,self指向MyModule,它没有private_b方法。如果您希望它以两种方式工作,您必须将private_b声明为模块方法,或者只需将行extend self添加到MyModule,这样它的所有方法都将成为模块方法。

#2


3  

module_function does copy your module_func_a into the metaclass but not its dependencies.

module_function会将module_func_a复制到元类中,但不会复制到其依赖项中。

So when calling module_func_a from an object, you get the other method private_b. But calling it on the module itself fails because private_b is not a module function.

因此,当从对象调用module_func_a时,您将获得另一个方法private_b。但是在模块本身上调用它会失败,因为private_b不是模块函数。

You should use module_function for private_b too and it should work.

您也应该将module_function用于private_b,它应该可以工作。

#1


6  

It works when you include the module in a class, because then all of the module's methods get included in that class (the self in module_func_a points to MyClass, which has also the private_b method).

当你在一个类中包含模块时,它可以工作,因为然后所有模块的方法都包含在该类中(module_func_a中的self指向MyClass,它也有private_b方法)。

In the other situation self points to MyModule, which does not have private_b method. If you wanted it to work both ways, you'd have to either declare private_b as a module method as well, or simply add the line extend self to MyModule, so that all it's methods would become module methods.

在另一种情况下,self指向MyModule,它没有private_b方法。如果您希望它以两种方式工作,您必须将private_b声明为模块方法,或者只需将行extend self添加到MyModule,这样它的所有方法都将成为模块方法。

#2


3  

module_function does copy your module_func_a into the metaclass but not its dependencies.

module_function会将module_func_a复制到元类中,但不会复制到其依赖项中。

So when calling module_func_a from an object, you get the other method private_b. But calling it on the module itself fails because private_b is not a module function.

因此,当从对象调用module_func_a时,您将获得另一个方法private_b。但是在模块本身上调用它会失败,因为private_b不是模块函数。

You should use module_function for private_b too and it should work.

您也应该将module_function用于private_b,它应该可以工作。