2012-04-06 8 views
7

test_module.rbRubí module_function, la invocación de método privado de módulo, invocado en el estilo método de clase en el módulo de muestra de error

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 

La invocación de la función del módulo de la clase

c = MyClass.new 
    c.test_module 

salida 1:

$ ruby test_module.rb 
module_func_a invoked 
private_b invoked 

Invocar la función módulo en módulo en estilo método de clase

ma = MyModule.module_func_a 

Producto 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 

Como puede verse a partir de la salida 1 y salida 2 cuando se incluye el módulo en una clase, no ocurre ningún problema cuando el método privado de un módulo se invoca desde una función de módulo mientras que en caso de invocar directamente la función de módulo en el módulo en c Estilo de método de lass no se encuentra el método privado del módulo, invocado desde la función del módulo.

¿Alguien puede hacerme entender la razón detrás del comportamiento anterior y si es posible o no invocar la función del módulo (que a su vez invoca el método privado del módulo) en el módulo en el estilo del método de clase? Si es posible, ¿qué rectificaciones son necesarias en mi código para hacer lo mismo?

Respuesta

6

funciona cuando se incluye el módulo en una clase, porque entonces todos los métodos del módulo sean incluidos en esa clase (los self en module_func_a puntos a MyClass, que tiene también el método private_b).

En la otra situación yo apunta a MyModule, que no tiene el método private_b. Si desea que funcione en ambos sentidos, debe declarar private_b como un método de módulo, o simplemente agregar la línea extend self al MyModule, de modo que todos sus métodos se conviertan en métodos de módulo.

+0

Thanks.This funciona.Traté de extender self a MyModule y está funcionando. Sin embargo, parece que en este caso privado parece redundante y no tiene ningún efecto. ¿Es que en casos como los mencionados no podemos crear métodos privados? Por ejemplo, necesito crear un método de utilidad que solo deba ser utilizado por instancia de módulo o funciones de módulo y no debe exponerse a los usuarios del módulo –

+0

No puede y por eso prefiero usar delegación. – psyho

+2

@pysho - ¿Puede darme un ejemplo o proporcionarme un enlace que proporcione detalles sobre cómo usar la delegación que mencionó? –

3

module_function copia su module_func_a en la metaclase pero no sus dependencias.

Por lo tanto, cuando llame a module_func_a desde un objeto, obtendrá el otro método private_b. Pero la llamada al módulo en sí falla porque private_b no es una función de módulo.

También debe usar module_function para private_b y debería funcionar.

Cuestiones relacionadas