2010-07-28 15 views
19

¿Es posible declarar métodos estáticos en un módulo en ruby?¿Métodos estáticos en módulos 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 

El ejemplo anterior no imprime "salido".

¿Solo es posible tener métodos de instancia en un módulo?

Respuesta

29

Definir su módulo como este (es decir, hacer exit un método de instancia en el módulo):

module Software 
    def exit 
    puts "exited" 
    end 
end 

y luego usar extend en lugar de include

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

En uso:

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

Ex aplanamiento

obj.extend(module, ...) se suma a obj los métodos de instancia de cada módulo dado como un parámetro

... así cuando se utiliza en el contexto de una definición de clase (con la clase en sí como el receptor) los métodos se convierten en métodos de clase.

0

Es posible incluir métodos estáticos en un módulo:

module Software 

    def self.exit 
    puts "exited" 

    end 
end 

Software.exit 

La ejecución de este imprime 'salieron' como se esperaba.

+0

pero ¿tengo que incluir este módulo dentro de la clase para usar el método estático? ¿causa include simplemente incluye métodos de instancia de un módulo no estático? –

+0

Ah, no estoy seguro de eso. Una solución fácil sería simplemente llamar a 'Software.exit' dentro de la clase de Windows y deshacerse de la parte 'incluir software' (no es la solución más elegante, pero está fuera del alcance de esta pregunta como se plantea actualmente). –

2

Dos cosas tienen que cambiar para ser capaz de llamar a Windows.exit:

  1. Software#exit necesidades de ser un método de instancia
  2. Windows necesidades de extendSoftware, no include ella.

Esto se debe a extend ing otro módulo pone métodos de instancia de ese módulo como clase métodos del módulo actual, mientras que include ing un módulo pone los métodos como nuevos métodos de instancia.

module Software 
    def exit 
     puts "exited" 
    end 
end 

class Windows 
    extend Software 

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

end 

Windows.start 

de salida es:

 
started 
exited 
12

Deja métodos de su clase en un módulo de anidado, y luego anular el "incluido" gancho. Este enlace se llama cada vez que se incluye su módulo.En el interior del gancho, añadir los métodos de la clase a quien hicieron el include:

module Foo 

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

    module ClassMethods 

    def foo 
     'foo' 
    end 

    end 

end 

Ahora, cualquier clase, incluyendo Foo consigue un método de la clase llamada foo:

class MyClass 
    include Foo 
end 

p MyClass.foo # "foo" 

Los métodos no-clase se pueden definir de Foo como siempre.

+0

(al lado: es MyClass.foo) Este enfoque tiene la ventaja de que también puede agregar funciones no estáticas. – Baju

+0

@Baju, ya sea '::' o '.' funciona allí, pero supongo que' .' se prefiere. He editado el ejemplo. Gracias por señalar eso. –

+0

-1. Yuck, esto es completamente innecesario. Simplemente use 'extender' en lugar de' incluir'. –