2010-04-19 17 views
17

Actualmente estoy trabajando en el libro Gregory Brown Ruby Best Practices. Al principio, él está hablando de la refacturación de algunas funcionalidades de los métodos de ayuda en una clase relacionada, a algunos métodos en el módulo, y luego tenía el módulo extend self.Cuándo usar un módulo y cuándo usar una clase

No había visto eso antes, después de un google rápido, descubrió que extend self en un módulo permite que los métodos definidos en el módulo se vean unos a otros, lo que tiene sentido.

Ahora, mi pregunta es ¿cuándo hacer algo como esto

module StyleParser 
    extend self 

    def process(text) 
    ... 
    end 

    def style_tag?(text) 
    ... 
    end 
end 

y luego referirse a él en las pruebas con

@parser = Prawn::Document::Text::StyleParser 

en contraposición a algo como esto?

class StyleParser 

    def self.process(text) 
    ... 
    end 

    def self.style_tag?(text) 
    ... 
    end 
end 

es para que pueda usarlo como mixin? o hay otras razones por las que no estoy viendo?

Respuesta

30

Una clase se debe utilizar para funcionalidad que requiera instanciación o que necesita realizar un seguimiento del estado. Un módulo se puede utilizar como una forma de combinar la funcionalidad en múltiples clases, o como una forma de proporcionar características únicas que no necesitan ser instanciadas o para hacer un seguimiento del estado. Un método de clase también podría usarse para este último.

Con esto en mente, creo que la distinción radica en si realmente necesita una clase o no. Un método de clase parece más apropiado cuando tienes una clase existente que necesita alguna funcionalidad singleton. Si lo que está haciendo solo consiste en métodos únicos, tiene más sentido implementarlo como un módulo y acceder a él a través del módulo directamente.

+1

Exactamente lo que estaba buscando :-) –

-2

Si es algo que desea crear una instancia, use una clase. El resto de tu pregunta necesita más contexto para tener sentido.

3

En este caso particular, probablemente no utilice ni una clase ni un módulo.

Una clase es una fábrica para objetos (tenga en cuenta el plural). Si no desea crear varias instancias de la clase, no es necesario que exista.

Un módulo es un contenedor de métodos, compartido entre múltiples objetos. Si no mezcla el módulo en múltiples objetos, no es necesario que exista.

En este caso, parece que solo quiere un objeto. Así que utilice uno:

def (StyleParser = Object.new).process(text) 
    ... 
end 

def StyleParser.style_tag?(text) 
    ... 
end 

O, alternativamente:

class << (StyleParser = Object.new) 
    def process(text) 
    ... 
    end 

    def style_tag?(text) 
    ... 
    end 
end 

Pero como ya @Azeem escribió: para una decisión adecuada, se necesita más contexto. No estoy lo suficientemente familiarizado con los aspectos internos de Gamba como para saber por qué Gregory tomó esa decisión en particular.

Cuestiones relacionadas