2012-06-09 14 views
55

Esto Ruby Style Guide dice que es mejor usar self.method_name en lugar de class method_name. ¿Pero por qué?class << self vs self.method with Ruby: qué hay mejor?

class TestClass 
    # bad 
    class << self 
    def first_method 
     # body omitted 
    end 

    def second_method_etc 
     # body omitted 
    end 
    end 

    # good 
    def self.first_method 
    # body omitted 
    end 

    def self.second_method_etc 
    # body omitted 
    end 
end 

¿Hay problemas de rendimiento?

+14

Es difícil tomar en serio una sugerencia de estilo si no hay una explicación que lo acompañe, ¿no es así? –

+3

Tenga en cuenta que dice "_Esta es una guía que usamos para nuestras propias aplicaciones de ruby ​​internamente en GitHub._" Es decir, este es el estilo que Github ha definido para su propio uso. No es una guía definitiva para corregir el estilo Ruby. –

+1

Estoy de acuerdo, pero parece estar escrito a partir de Rubyists bien formados con habilidades de autoridad. –

Respuesta

75

class << self es bueno para mantener todos los métodos de su clase en el mismo bloque. Si se agregan métodos en def self.method a partir de entonces, no hay garantía (aparte de la convención y las ilusiones) de que no habrá un método de clase adicional guardado más adelante en el archivo.

def self.method es bueno para indicar explícitamente que un método es un método de clase, mientras que con class << self tiene que ir y buscar el contenedor usted mismo.

Cuál de estos es más importante para usted es una decisión subjetiva, y también depende de cosas como cuántas personas están trabajando en el código y cuáles son sus preferencias.

+6

No estoy de acuerdo, esta no es solo una simple elección personal. Hay una desventaja de legibilidad de código para usar '<<' - ver la respuesta de @Flexoid. La desventaja de la sintaxis 'class << self' y el uso de un bloque de código, es que si el bloque es más largo que unos pocos métodos, no es evidente que estos métodos sean de clase, a menos que se desplace hasta la' clase << sección del self' –

+1

Sin embargo, ese no es un problema específico de 'clase << self '. He visto muchos archivos fuente (más a menudo en proyectos grandes y no triviales) con anidamiento profundo de módulos, donde no está claro hasta que se desplaza hacia arriba en qué clase * hay un método en – Gareth

+0

@DmitriZagidulin. En ese caso, puede decir estos los métodos son métodos de clase basados ​​en indention. – weakish

5

Supongo que piensan que self.* es mejor porque se puede decir con certeza, es un método de clase o instancia, sin tener que desplazarse hacia arriba y buscar esta cadena class << self.

+1

Estoy sorprendido por las otras respuestas a esta pregunta; esta es la única forma sensata de hacerlo. Si escribe 'clase << self ', es evidente para el lector que los métodos son métodos de clase si a) solo tiene un número pequeño de ellos, * AND * b) la línea' class << self' es actualmente visible en tu editor También es fácil grep para métodos de clase e instancia si sigues la convención 'def self.thing'. Dave Thomas sugiere que '<< self' esté reservado para cuando necesite cambiar' self' (dentro del bloque, por ejemplo, para llamar a attr_accessor en la clase). –

+1

Pero en ese momento, ¿sería tan "ilegible" tener métodos privados? ya que todos están sangrados bajo la palabra clave "privada". Supongo que en ruby ​​puede llamar explícitamente "private: method" para cada método, pero dado cómo funciona la sintaxis C, creo que no es irracional esperar que los desarrolladores sepan que las definiciones de función/método pueden tener contexto a su alrededor. –

28

En general, class << self se utiliza en la metaprogramación para establecer la clase como propia por un período de tiempo prolongado. Si estoy tratando de escribir 10 métodos, lo usaría así:

METHOD_APPENDICES = [1...10] 
class << self 
    METHOD_APPENDICES.each do |n| 
    define_method("method#{n}") { n } 
    end 
end 

Esto crearía 10 métodos (metodo1, metodo2, metodo3, etc.) que acaba de devolver el número. Yo usaría class << self para mayor claridad en este caso porque en la metaprogramación self es crucial. Tirar basura en self. dentro realmente haría que las cosas menos legibles.

Si solo está definiendo los métodos de clase normalmente, adhiérase a self.class_method_name porque es probable que más personas lo entiendan. No es necesario incluir meta-sintaxis a menos que espere que su audiencia lo entienda.

+0

Imho, la mejor respuesta. Sin embargo, da una razón no subjetiva en que Ruby tiene 2 estilos de sintaxis para definir el método de clase. – 18augst

3

Cualquiera que usted quiera. Ambos son muy claros para lo que haces. Pero pienso en algunas recomendaciones para esto.

Cuando solo hay un método de clase para definir, Utilice def self.xxx. Porque para definir solo un método, aumentar el nivel de sangría probablemente se vuelva abigarrado.

Cuando hay más de un método de clase para definir, Use class << self. Porque escribir def self.xxx, def self.yyy y def self.zzz es sin duda la repetición. Crea una sección para estos métodos.

Cuando todos los métodos en una clase son método de clase, puede utilizar module con module_function en lugar de class. Esto le permite definir las funciones del módulo simplemente use def xxx.

+1

'extender self' no funcionará con la clase. –

+0

Gracias por un comentario. Arreglé mi respuesta. – nonowarn

19

Como se señaló anteriormente, ambos estilos parecen ser equivalentes, sin embargo, usar class << self permite marcar los métodos de clase como private o protected.Por ejemplo:

class UsingDefSelf 
    def self.a; 'public class method'; end 
    private 
    def self.b; 'public class method!'; end 
end 

class UsingSingletonClass 
    class << self 
    def a; 'public class method'; end 
    private 
    def b; 'private class method'; end 
    end 
end 

private solo afecta a los métodos de instancia. Usando la clase singleton, estamos definiendo métodos de instancia de esa clase, que se convierten en métodos de clase de la clase contenedora.

También puede marcar los métodos de clase como private con def self:

class UsingDefSelf 
    def self.a; 'private class method'; end 
    def self.b; 'private class method!'; end 
    private_class_method :a, :b 
    # In Ruby 2.1 there is an alternative syntax 
    private_class_method def self.c; 'private class method!'; end 
end 

, pero no podemos marcarlos como protected, no hay protected_class_method. (Sin embargo, ya que la clase es el único caso de su SingletonClass, método de clase privada y métodos de clases protegidas son casi los mismos, excepto su llamado sintaxis es diferente.)

También es menos fácil que usar class << self para marcar private métodos de clase, ya que tiene que enumerar todos los nombres de métodos en private_class_method o prefijo private_class_method a cada definición de método de clase privada.

-1

Hasta ahora, la pregunta y las respuestas sólo se discuten estas dos opciones:

class MyClass 
    def self.method_name 
    .. 
    end 
end 

class MyClass 
    class << self 
    def method_name 
     .. 
    end 
    end 
end 

Pero aquí hay otra opción a considerar para los métodos de la clase/métodos simples/métodos estáticos/métodos que operan en el nivel de clase (o cualquier otra cosa al que desea llamar ellos):

class MyClass 
    def MyClass.method_name 
    .. 
    end 
end 

prefiero esta opción porque es más evidente lo que hace. La definición del método se asemeja a cómo se llamaría en su código, y está claro que opera en el nivel de clase.

También provengo de un fondo de Python donde self se usa por ejemplo en métodos, mientras que en Ruby, self se usa para métodos de clase. Esto a menudo me confunde, así que para evitar pensar "¿es un método propio en Ruby una clase o método de instancia?" Yo uso def ClassName.methodname.

+0

"También provengo de un fondo de Python donde self se usa por ejemplo, mientras que en Ruby, self se usa para métodos de clase. Esto a menudo me confunde" <- Esto es porque en Ruby "clase" es una "instancia". Y en el método de instancia Python es 'def m (self, args):', y Ruby es def(args) (simplemente omita "self" y ":"). – weakish

+2

Por favor, no use este estilo, el rubí es un idioma con una comunidad altamente dogmática. Esto permite a los desarrolladores codificar uno al lado del otro sin explicar demasiado o en cosas. Esto solo establece sus propios estándares únicos. –

+0

@AditSaxena teniendo una guía de estilo para su proyecto/equipo resuelve eso. (FWIW, ya no uso la opción que propuse porque ahora programo casi exclusivamente en Ruby y me he acostumbrado a 'self', pero aún es bueno saber sobre las diferentes opciones). – Dennis

Cuestiones relacionadas