2011-08-30 18 views
7

Me gustaría que parte de mi módulo extienda la clase String.Metaprogramación básica: ¿extender una clase existente usando un módulo?

Esto no funciona

module MyModule 
    class String 
    def exclaim 
     self << "!!!!!" 
    end 
    end 
end 

include MyModule 

string = "this is a string" 
string.exclaim 

#=> NoMethodError 

Pero esto hace

module MyModule 
    def exclaim 
    self << "!!!!!" 
    end 
end 

class String 
    include MyModule 
end 

string = "this is a string" 
string.exclaim 

#=> "this is a string!!!!!" 

que no quieren los demás funcionalidad de MyModule a ser abandonado en la cadena. Volver a incluirlo al más alto nivel parece feo. Seguramente hay una manera más clara de hacer esto?

Respuesta

25

El método exclaim en su primer ejemplo se está definiendo dentro de una clase llamada MyModule::String, que no tiene nada que ver con la clase estándar String.

Dentro de su módulo, puede abrir la String clase estándar (en el espacio de nombres global) así:

module MyModule 
    class ::String 
    # ‘Multiple exclamation marks,’ he went on, shaking his head, 
    # ‘are a sure sign of a diseased mind.’ — Terry Pratchett, “Eric” 
    def exclaim 
     self << "!!!!" 
    end 
    end 
end 
+0

muy útil. gracias. – djb

+0

Voto a favor para la cita en los comentarios :-) – vijucat

1

no estoy seguro de que he entendido su pregunta, pero ¿por qué no se abre la cadena en un archivo, digo exclaim.rb, y luego requiero que cuando lo necesite:

exclaim.rb

class String 
    def exclaim 
     self << "!!!!!" 
    end 
    end 

y luego

require "exclaim" 

"hello".exclaim 

Pero tal vez me estoy perdiendo algo?

+0

Si esto funciona. Pero mi pregunta es, ¿se puede modificar String directamente desde dentro de un módulo? – djb

+0

Oh ... ahora tengo su pregunta. Afortunadamente, @Lars Haugseth lo hizo :) – lucapette

Cuestiones relacionadas